aboutsummaryrefslogtreecommitdiff
path: root/src/org/apache/harmony/javax
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/apache/harmony/javax')
-rw-r--r--src/org/apache/harmony/javax/security/auth/AuthPermission.java97
-rw-r--r--src/org/apache/harmony/javax/security/auth/DestroyFailedException.java44
-rw-r--r--src/org/apache/harmony/javax/security/auth/Destroyable.java43
-rw-r--r--src/org/apache/harmony/javax/security/auth/PrivateCredentialPermission.java395
-rw-r--r--src/org/apache/harmony/javax/security/auth/RefreshFailedException.java31
-rw-r--r--src/org/apache/harmony/javax/security/auth/Refreshable.java26
-rw-r--r--src/org/apache/harmony/javax/security/auth/Subject.java782
-rw-r--r--src/org/apache/harmony/javax/security/auth/SubjectDomainCombiner.java123
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/Callback.java25
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/CallbackHandler.java54
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/ChoiceCallback.java109
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/ConfirmationCallback.java234
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/LanguageCallback.java41
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/NameCallback.java74
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/PasswordCallback.java124
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/TextInputCallback.java74
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/TextOutputCallback.java56
-rw-r--r--src/org/apache/harmony/javax/security/auth/callback/UnsupportedCallbackException.java64
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/AccountException.java31
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/AccountExpiredException.java31
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/AccountLockedException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/AccountNotFoundException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/AppConfigurationEntry.java95
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/Configuration.java102
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/CredentialException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/CredentialExpiredException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/CredentialNotFoundException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/FailedLoginException.java32
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/LoginContext.java548
-rw-r--r--src/org/apache/harmony/javax/security/auth/login/LoginException.java45
-rw-r--r--src/org/apache/harmony/javax/security/auth/spi/LoginModule.java38
-rw-r--r--src/org/apache/harmony/javax/security/sasl/AuthenticationException.java35
-rw-r--r--src/org/apache/harmony/javax/security/sasl/AuthorizeCallback.java79
-rw-r--r--src/org/apache/harmony/javax/security/sasl/RealmCallback.java33
-rw-r--r--src/org/apache/harmony/javax/security/sasl/RealmChoiceCallback.java30
-rw-r--r--src/org/apache/harmony/javax/security/sasl/Sasl.java204
-rw-r--r--src/org/apache/harmony/javax/security/sasl/SaslClient.java37
-rw-r--r--src/org/apache/harmony/javax/security/sasl/SaslClientFactory.java30
-rw-r--r--src/org/apache/harmony/javax/security/sasl/SaslException.java69
-rw-r--r--src/org/apache/harmony/javax/security/sasl/SaslServer.java37
-rw-r--r--src/org/apache/harmony/javax/security/sasl/SaslServerFactory.java30
41 files changed, 4062 insertions, 0 deletions
diff --git a/src/org/apache/harmony/javax/security/auth/AuthPermission.java b/src/org/apache/harmony/javax/security/auth/AuthPermission.java
new file mode 100644
index 0000000..bb12554
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/AuthPermission.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+import java.security.BasicPermission;
+
+
+
+/**
+ * Governs the use of methods in this package and also its subpackages. A
+ * <i>target name</i> of the permission specifies which methods are allowed
+ * without specifying the concrete action lists. Possible target names and
+ * associated authentication permissions are:
+ *
+ * <pre>
+ * doAs invoke Subject.doAs methods.
+ * doAsPrivileged invoke the Subject.doAsPrivileged methods.
+ * getSubject invoke Subject.getSubject().
+ * getSubjectFromDomainCombiner invoke SubjectDomainCombiner.getSubject().
+ * setReadOnly invoke Subject.setReadonly().
+ * modifyPrincipals modify the set of principals
+ * associated with a Subject.
+ * modifyPublicCredentials modify the set of public credentials
+ * associated with a Subject.
+ * modifyPrivateCredentials modify the set of private credentials
+ * associated with a Subject.
+ * refreshCredential invoke the refresh method on a credential of a
+ * refreshable credential class.
+ * destroyCredential invoke the destroy method on a credential of a
+ * destroyable credential class.
+ * createLoginContext.<i>name</i> instantiate a LoginContext with the
+ * specified name. The wildcard name ('*')
+ * allows to a LoginContext of any name.
+ * getLoginConfiguration invoke the getConfiguration method of
+ * javax.security.auth.login.Configuration.
+ * refreshLoginConfiguration Invoke the refresh method of
+ * javax.security.auth.login.Configuration.
+ * </pre>
+ */
+public final class AuthPermission extends BasicPermission {
+
+ private static final long serialVersionUID = 5806031445061587174L;
+
+ private static final String CREATE_LOGIN_CONTEXT = "createLoginContext"; //$NON-NLS-1$
+
+ private static final String CREATE_LOGIN_CONTEXT_ANY = "createLoginContext.*"; //$NON-NLS-1$
+
+ // inits permission name.
+ private static String init(String name) {
+
+ if (name == null) {
+ throw new NullPointerException("auth.13"); //$NON-NLS-1$
+ }
+
+ if (CREATE_LOGIN_CONTEXT.equals(name)) {
+ return CREATE_LOGIN_CONTEXT_ANY;
+ }
+ return name;
+ }
+
+ /**
+ * Creates an authentication permission with the specified target name.
+ *
+ * @param name
+ * the target name of this authentication permission.
+ */
+ public AuthPermission(String name) {
+ super(init(name));
+ }
+
+ /**
+ * Creates an authentication permission with the specified target name.
+ *
+ * @param name
+ * the target name of this authentication permission.
+ * @param actions
+ * this parameter is ignored and should be {@code null}.
+ */
+ public AuthPermission(String name, String actions) {
+ super(init(name), actions);
+ }
+} \ No newline at end of file
diff --git a/src/org/apache/harmony/javax/security/auth/DestroyFailedException.java b/src/org/apache/harmony/javax/security/auth/DestroyFailedException.java
new file mode 100644
index 0000000..7c7ea79
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/DestroyFailedException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+/**
+ * Signals that the {@link Destroyable#destroy()} method failed.
+ */
+public class DestroyFailedException extends Exception {
+
+ private static final long serialVersionUID = -7790152857282749162L;
+
+ /**
+ * Creates an exception of type {@code DestroyFailedException}.
+ */
+ public DestroyFailedException() {
+ super();
+ }
+
+ /**
+ * Creates an exception of type {@code DestroyFailedException}.
+ *
+ * @param message
+ * A detail message that describes the reason for this exception.
+ */
+ public DestroyFailedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/Destroyable.java b/src/org/apache/harmony/javax/security/auth/Destroyable.java
new file mode 100644
index 0000000..12a107b
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/Destroyable.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+/**
+ * Allows for special treatment of sensitive information, when it comes to
+ * destroying or clearing of the data.
+ */
+public interface Destroyable {
+
+ /**
+ * Erases the sensitive information. Once an object is destroyed any calls
+ * to its methods will throw an {@code IllegalStateException}. If it does
+ * not succeed a DestroyFailedException is thrown.
+ *
+ * @throws DestroyFailedException
+ * if the information cannot be erased.
+ */
+ void destroy() throws DestroyFailedException;
+
+ /**
+ * Returns {@code true} once an object has been safely destroyed.
+ *
+ * @return whether the object has been safely destroyed.
+ */
+ boolean isDestroyed();
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/PrivateCredentialPermission.java b/src/org/apache/harmony/javax/security/auth/PrivateCredentialPermission.java
new file mode 100644
index 0000000..d62bb24
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/PrivateCredentialPermission.java
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Principal;
+import java.util.Set;
+
+
+
+/**
+ * Protects private credential objects belonging to a {@code Subject}. It has
+ * only one action which is "read". The target name of this permission has a
+ * special syntax:
+ *
+ * <pre>
+ * targetName = CredentialClass {PrincipalClass &quot;PrincipalName&quot;}*
+ * </pre>
+ *
+ * First it states a credential class and is followed then by a list of one or
+ * more principals identifying the subject.
+ * <p>
+ * The principals on their part are specified as the name of the {@code
+ * Principal} class followed by the principal name in quotes. For example, the
+ * following file may define permission to read the private credentials of a
+ * principal named "Bob": "com.sun.PrivateCredential com.sun.Principal \"Bob\""
+ * <p>
+ * The syntax also allows the use of the wildcard "*" in place of {@code
+ * CredentialClass} or {@code PrincipalClass} and/or {@code PrincipalName}.
+ *
+ * @see Principal
+ */
+public final class PrivateCredentialPermission extends Permission {
+
+ private static final long serialVersionUID = 5284372143517237068L;
+
+ // allowed action
+ private static final String READ = "read"; //$NON-NLS-1$
+
+ private String credentialClass;
+
+ // current offset
+ private transient int offset;
+
+ // owners set
+ private transient CredOwner[] set;
+
+ /**
+ * Creates a new permission for private credentials specified by the target
+ * name {@code name} and an {@code action}. The action is always
+ * {@code "read"}.
+ *
+ * @param name
+ * the target name of the permission.
+ * @param action
+ * the action {@code "read"}.
+ */
+ public PrivateCredentialPermission(String name, String action) {
+ super(name);
+ if (READ.equalsIgnoreCase(action)) {
+ initTargetName(name);
+ } else {
+ throw new IllegalArgumentException("auth.11"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Creates a {@code PrivateCredentialPermission} from the {@code Credential}
+ * class and set of principals.
+ *
+ * @param credentialClass
+ * the credential class name.
+ * @param principals
+ * the set of principals.
+ */
+ PrivateCredentialPermission(String credentialClass, Set<Principal> principals) {
+ super(credentialClass);
+ this.credentialClass = credentialClass;
+
+ set = new CredOwner[principals.size()];
+ for (Principal p : principals) {
+ CredOwner element = new CredOwner(p.getClass().getName(), p.getName());
+ // check for duplicate elements
+ boolean found = false;
+ for (int ii = 0; ii < offset; ii++) {
+ if (set[ii].equals(element)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ set[offset++] = element;
+ }
+ }
+ }
+
+ /**
+ * Initialize a PrivateCredentialPermission object and checks that a target
+ * name has a correct format: CredentialClass 1*(PrincipalClass
+ * "PrincipalName")
+ */
+ private void initTargetName(String name) {
+
+ if (name == null) {
+ throw new NullPointerException("auth.0E"); //$NON-NLS-1$
+ }
+
+ // check empty string
+ name = name.trim();
+ if (name.length() == 0) {
+ throw new IllegalArgumentException("auth.0F"); //$NON-NLS-1$
+ }
+
+ // get CredentialClass
+ int beg = name.indexOf(' ');
+ if (beg == -1) {
+ throw new IllegalArgumentException("auth.10"); //$NON-NLS-1$
+ }
+ credentialClass = name.substring(0, beg);
+
+ // get a number of pairs: PrincipalClass "PrincipalName"
+ beg++;
+ int count = 0;
+ int nameLength = name.length();
+ for (int i, j = 0; beg < nameLength; beg = j + 2, count++) {
+ i = name.indexOf(' ', beg);
+ j = name.indexOf('"', i + 2);
+
+ if (i == -1 || j == -1 || name.charAt(i + 1) != '"') {
+ throw new IllegalArgumentException("auth.10"); //$NON-NLS-1$
+ }
+ }
+
+ // name MUST have one pair at least
+ if (count < 1) {
+ throw new IllegalArgumentException("auth.10"); //$NON-NLS-1$
+ }
+
+ beg = name.indexOf(' ');
+ beg++;
+
+ // populate principal set with instances of CredOwner class
+ String principalClass;
+ String principalName;
+
+ set = new CredOwner[count];
+ for (int index = 0, i, j; index < count; beg = j + 2, index++) {
+ i = name.indexOf(' ', beg);
+ j = name.indexOf('"', i + 2);
+
+ principalClass = name.substring(beg, i);
+ principalName = name.substring(i + 2, j);
+
+ CredOwner element = new CredOwner(principalClass, principalName);
+ // check for duplicate elements
+ boolean found = false;
+ for (int ii = 0; ii < offset; ii++) {
+ if (set[ii].equals(element)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ set[offset++] = element;
+ }
+ }
+ }
+
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ initTargetName(getName());
+ }
+
+ /**
+ * Returns the principal's classes and names associated with this {@code
+ * PrivateCredentialPermission} as a two dimensional array. The first
+ * dimension of the array corresponds to the number of principals. The
+ * second dimension defines either the name of the {@code PrincipalClass}
+ * [x][0] or the value of {@code PrincipalName} [x][1].
+ * <p>
+ * This corresponds to the the target name's syntax:
+ *
+ * <pre>
+ * targetName = CredentialClass {PrincipalClass &quot;PrincipalName&quot;}*
+ * </pre>
+ *
+ * @return the principal classes and names associated with this {@code
+ * PrivateCredentialPermission}.
+ */
+ public String[][] getPrincipals() {
+
+ String[][] s = new String[offset][2];
+
+ for (int i = 0; i < s.length; i++) {
+ s[i][0] = set[i].principalClass;
+ s[i][1] = set[i].principalName;
+ }
+ return s;
+ }
+
+ @Override
+ public String getActions() {
+ return READ;
+ }
+
+ /**
+ * Returns the class name of the credential associated with this permission.
+ *
+ * @return the class name of the credential associated with this permission.
+ */
+ public String getCredentialClass() {
+ return credentialClass;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 0;
+ for (int i = 0; i < offset; i++) {
+ hash = hash + set[i].hashCode();
+ }
+ return getCredentialClass().hashCode() + hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj == null || this.getClass() != obj.getClass()) {
+ return false;
+ }
+
+ PrivateCredentialPermission that = (PrivateCredentialPermission) obj;
+
+ return credentialClass.equals(that.credentialClass) && (offset == that.offset)
+ && sameMembers(set, that.set, offset);
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+
+ if (permission == null || this.getClass() != permission.getClass()) {
+ return false;
+ }
+
+ PrivateCredentialPermission that = (PrivateCredentialPermission) permission;
+
+ if (!("*".equals(credentialClass) || credentialClass //$NON-NLS-1$
+ .equals(that.getCredentialClass()))) {
+ return false;
+ }
+
+ if (that.offset == 0) {
+ return true;
+ }
+
+ CredOwner[] thisCo = set;
+ CredOwner[] thatCo = that.set;
+ int thisPrincipalsSize = offset;
+ int thatPrincipalsSize = that.offset;
+ for (int i = 0, j; i < thisPrincipalsSize; i++) {
+ for (j = 0; j < thatPrincipalsSize; j++) {
+ if (thisCo[i].implies(thatCo[j])) {
+ break;
+ }
+ }
+ if (j == thatCo.length) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public PermissionCollection newPermissionCollection() {
+ return null;
+ }
+
+ /**
+ * Returns true if the two arrays have the same length, and every member of
+ * one array is contained in another array
+ */
+ private boolean sameMembers(Object[] ar1, Object[] ar2, int length) {
+ if (ar1 == null && ar2 == null) {
+ return true;
+ }
+ if (ar1 == null || ar2 == null) {
+ return false;
+ }
+ boolean found;
+ for (int i = 0; i < length; i++) {
+ found = false;
+ for (int j = 0; j < length; j++) {
+ if (ar1[i].equals(ar2[j])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static final class CredOwner implements Serializable {
+
+ private static final long serialVersionUID = -5607449830436408266L;
+
+ String principalClass;
+
+ String principalName;
+
+ // whether class name contains wildcards
+ private transient boolean isClassWildcard;
+
+ // whether pname contains wildcards
+ private transient boolean isPNameWildcard;
+
+ // Creates a new CredOwner with the specified Principal Class and Principal Name
+ CredOwner(String principalClass, String principalName) {
+ super();
+ if ("*".equals(principalClass)) { //$NON-NLS-1$
+ isClassWildcard = true;
+ }
+
+ if ("*".equals(principalName)) { //$NON-NLS-1$
+ isPNameWildcard = true;
+ }
+
+ if (isClassWildcard && !isPNameWildcard) {
+ throw new IllegalArgumentException("auth.12"); //$NON-NLS-1$
+ }
+
+ this.principalClass = principalClass;
+ this.principalName = principalName;
+ }
+
+ // Checks if this CredOwner implies the specified Object.
+ boolean implies(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ CredOwner co = (CredOwner) obj;
+
+ if (isClassWildcard || principalClass.equals(co.principalClass)) {
+ if (isPNameWildcard || principalName.equals(co.principalName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Checks two CredOwner objects for equality.
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof CredOwner) {
+ CredOwner that = (CredOwner) obj;
+ return principalClass.equals(that.principalClass)
+ && principalName.equals(that.principalName);
+ }
+ return false;
+ }
+
+ // Returns the hash code value for this object.
+ @Override
+ public int hashCode() {
+ return principalClass.hashCode() + principalName.hashCode();
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/RefreshFailedException.java b/src/org/apache/harmony/javax/security/auth/RefreshFailedException.java
new file mode 100644
index 0000000..71bcc6b
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/RefreshFailedException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+public class RefreshFailedException extends Exception {
+
+ private static final long serialVersionUID = 5058444488565265840L;
+
+ public RefreshFailedException() {
+ super();
+ }
+
+ public RefreshFailedException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/Refreshable.java b/src/org/apache/harmony/javax/security/auth/Refreshable.java
new file mode 100644
index 0000000..90b00cb
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/Refreshable.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+public interface Refreshable {
+
+ void refresh() throws RefreshFailedException;
+
+ boolean isCurrent();
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/Subject.java b/src/org/apache/harmony/javax/security/auth/Subject.java
new file mode 100644
index 0000000..142686e
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/Subject.java
@@ -0,0 +1,782 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.DomainCombiner;
+import java.security.Permission;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+
+
+
+/**
+ * The central class of the {@code javax.security.auth} package representing an
+ * authenticated user or entity (both referred to as "subject"). IT defines also
+ * the static methods that allow code to be run, and do modifications according
+ * to the subject's permissions.
+ * <p>
+ * A subject has the following features:
+ * <ul>
+ * <li>A set of {@code Principal} objects specifying the identities bound to a
+ * {@code Subject} that distinguish it.</li>
+ * <li>Credentials (public and private) such as certificates, keys, or
+ * authentication proofs such as tickets</li>
+ * </ul>
+ */
+public final class Subject implements Serializable {
+
+ private static final long serialVersionUID = -8308522755600156056L;
+
+ private static final AuthPermission _AS = new AuthPermission("doAs"); //$NON-NLS-1$
+
+ private static final AuthPermission _AS_PRIVILEGED = new AuthPermission(
+ "doAsPrivileged"); //$NON-NLS-1$
+
+ private static final AuthPermission _SUBJECT = new AuthPermission(
+ "getSubject"); //$NON-NLS-1$
+
+ private static final AuthPermission _PRINCIPALS = new AuthPermission(
+ "modifyPrincipals"); //$NON-NLS-1$
+
+ private static final AuthPermission _PRIVATE_CREDENTIALS = new AuthPermission(
+ "modifyPrivateCredentials"); //$NON-NLS-1$
+
+ private static final AuthPermission _PUBLIC_CREDENTIALS = new AuthPermission(
+ "modifyPublicCredentials"); //$NON-NLS-1$
+
+ private static final AuthPermission _READ_ONLY = new AuthPermission(
+ "setReadOnly"); //$NON-NLS-1$
+
+ private final Set<Principal> principals;
+
+ private boolean readOnly;
+
+ // set of private credentials
+ private transient SecureSet<Object> privateCredentials;
+
+ // set of public credentials
+ private transient SecureSet<Object> publicCredentials;
+
+ /**
+ * The default constructor initializing the sets of public and private
+ * credentials and principals with the empty set.
+ */
+ public Subject() {
+ super();
+ principals = new SecureSet<Principal>(_PRINCIPALS);
+ publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
+ privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
+
+ readOnly = false;
+ }
+
+ /**
+ * The constructor for the subject, setting its public and private
+ * credentials and principals according to the arguments.
+ *
+ * @param readOnly
+ * {@code true} if this {@code Subject} is read-only, thus
+ * preventing any modifications to be done.
+ * @param subjPrincipals
+ * the set of Principals that are attributed to this {@code
+ * Subject}.
+ * @param pubCredentials
+ * the set of public credentials that distinguish this {@code
+ * Subject}.
+ * @param privCredentials
+ * the set of private credentials that distinguish this {@code
+ * Subject}.
+ */
+ public Subject(boolean readOnly, Set<? extends Principal> subjPrincipals,
+ Set<?> pubCredentials, Set<?> privCredentials) {
+
+ if (subjPrincipals == null || pubCredentials == null || privCredentials == null) {
+ throw new NullPointerException();
+ }
+
+ principals = new SecureSet<Principal>(_PRINCIPALS, subjPrincipals);
+ publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS, pubCredentials);
+ privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS, privCredentials);
+
+ this.readOnly = readOnly;
+ }
+
+ /**
+ * Runs the code defined by {@code action} using the permissions granted to
+ * the {@code Subject} itself and to the code as well.
+ *
+ * @param subject
+ * the distinguished {@code Subject}.
+ * @param action
+ * the code to be run.
+ * @return the {@code Object} returned when running the {@code action}.
+ */
+ @SuppressWarnings("unchecked")
+ public static Object doAs(Subject subject, PrivilegedAction action) {
+
+ checkPermission(_AS);
+
+ return doAs_PrivilegedAction(subject, action, AccessController.getContext());
+ }
+
+ /**
+ * Run the code defined by {@code action} using the permissions granted to
+ * the {@code Subject} and to the code itself, additionally providing a more
+ * specific context.
+ *
+ * @param subject
+ * the distinguished {@code Subject}.
+ * @param action
+ * the code to be run.
+ * @param context
+ * the specific context in which the {@code action} is invoked.
+ * if {@code null} a new {@link AccessControlContext} is
+ * instantiated.
+ * @return the {@code Object} returned when running the {@code action}.
+ */
+ @SuppressWarnings("unchecked")
+ public static Object doAsPrivileged(Subject subject, PrivilegedAction action,
+ AccessControlContext context) {
+
+ checkPermission(_AS_PRIVILEGED);
+
+ if (context == null) {
+ return doAs_PrivilegedAction(subject, action, new AccessControlContext(
+ new ProtectionDomain[0]));
+ }
+ return doAs_PrivilegedAction(subject, action, context);
+ }
+
+ // instantiates a new context and passes it to AccessController
+ @SuppressWarnings("unchecked")
+ private static Object doAs_PrivilegedAction(Subject subject, PrivilegedAction action,
+ final AccessControlContext context) {
+
+ AccessControlContext newContext;
+
+ final SubjectDomainCombiner combiner;
+ if (subject == null) {
+ // performance optimization
+ // if subject is null there is nothing to combine
+ combiner = null;
+ } else {
+ combiner = new SubjectDomainCombiner(subject);
+ }
+
+ PrivilegedAction dccAction = new PrivilegedAction() {
+ public Object run() {
+
+ return new AccessControlContext(context, combiner);
+ }
+ };
+
+ newContext = (AccessControlContext) AccessController.doPrivileged(dccAction);
+
+ return AccessController.doPrivileged(action, newContext);
+ }
+
+ /**
+ * Runs the code defined by {@code action} using the permissions granted to
+ * the subject and to the code itself.
+ *
+ * @param subject
+ * the distinguished {@code Subject}.
+ * @param action
+ * the code to be run.
+ * @return the {@code Object} returned when running the {@code action}.
+ * @throws PrivilegedActionException
+ * if running the {@code action} throws an exception.
+ */
+ @SuppressWarnings("unchecked")
+ public static Object doAs(Subject subject, PrivilegedExceptionAction action)
+ throws PrivilegedActionException {
+
+ checkPermission(_AS);
+
+ return doAs_PrivilegedExceptionAction(subject, action, AccessController.getContext());
+ }
+
+ /**
+ * Runs the code defined by {@code action} using the permissions granted to
+ * the subject and to the code itself, additionally providing a more
+ * specific context.
+ *
+ * @param subject
+ * the distinguished {@code Subject}.
+ * @param action
+ * the code to be run.
+ * @param context
+ * the specific context in which the {@code action} is invoked.
+ * if {@code null} a new {@link AccessControlContext} is
+ * instantiated.
+ * @return the {@code Object} returned when running the {@code action}.
+ * @throws PrivilegedActionException
+ * if running the {@code action} throws an exception.
+ */
+ @SuppressWarnings("unchecked")
+ public static Object doAsPrivileged(Subject subject,
+ PrivilegedExceptionAction action, AccessControlContext context)
+ throws PrivilegedActionException {
+
+ checkPermission(_AS_PRIVILEGED);
+
+ if (context == null) {
+ return doAs_PrivilegedExceptionAction(subject, action,
+ new AccessControlContext(new ProtectionDomain[0]));
+ }
+ return doAs_PrivilegedExceptionAction(subject, action, context);
+ }
+
+ // instantiates a new context and passes it to AccessController
+ @SuppressWarnings("unchecked")
+ private static Object doAs_PrivilegedExceptionAction(Subject subject,
+ PrivilegedExceptionAction action, final AccessControlContext context)
+ throws PrivilegedActionException {
+
+ AccessControlContext newContext;
+
+ final SubjectDomainCombiner combiner;
+ if (subject == null) {
+ // performance optimization
+ // if subject is null there is nothing to combine
+ combiner = null;
+ } else {
+ combiner = new SubjectDomainCombiner(subject);
+ }
+
+ PrivilegedAction<AccessControlContext> dccAction = new PrivilegedAction<AccessControlContext>() {
+ public AccessControlContext run() {
+ return new AccessControlContext(context, combiner);
+ }
+ };
+
+ newContext = AccessController.doPrivileged(dccAction);
+
+ return AccessController.doPrivileged(action, newContext);
+ }
+
+ /**
+ * Checks two Subjects for equality. More specifically if the principals,
+ * public and private credentials are equal, equality for two {@code
+ * Subjects} is implied.
+ *
+ * @param obj
+ * the {@code Object} checked for equality with this {@code
+ * Subject}.
+ * @return {@code true} if the specified {@code Subject} is equal to this
+ * one.
+ */
+ @Override
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || this.getClass() != obj.getClass()) {
+ return false;
+ }
+
+ Subject that = (Subject) obj;
+
+ if (principals.equals(that.principals)
+ && publicCredentials.equals(that.publicCredentials)
+ && privateCredentials.equals(that.privateCredentials)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns this {@code Subject}'s {@link Principal}.
+ *
+ * @return this {@code Subject}'s {@link Principal}.
+ */
+ public Set<Principal> getPrincipals() {
+ return principals;
+ }
+
+
+ /**
+ * Returns this {@code Subject}'s {@link Principal} which is a subclass of
+ * the {@code Class} provided.
+ *
+ * @param c
+ * the {@code Class} as a criteria which the {@code Principal}
+ * returned must satisfy.
+ * @return this {@code Subject}'s {@link Principal}. Modifications to the
+ * returned set of {@code Principal}s do not affect this {@code
+ * Subject}'s set.
+ */
+ public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
+ return ((SecureSet<Principal>) principals).get(c);
+ }
+
+ /**
+ * Returns the private credentials associated with this {@code Subject}.
+ *
+ * @return the private credentials associated with this {@code Subject}.
+ */
+ public Set<Object> getPrivateCredentials() {
+ return privateCredentials;
+ }
+
+ /**
+ * Returns this {@code Subject}'s private credentials which are a subclass
+ * of the {@code Class} provided.
+ *
+ * @param c
+ * the {@code Class} as a criteria which the private credentials
+ * returned must satisfy.
+ * @return this {@code Subject}'s private credentials. Modifications to the
+ * returned set of credentials do not affect this {@code Subject}'s
+ * credentials.
+ */
+ public <T> Set<T> getPrivateCredentials(Class<T> c) {
+ return privateCredentials.get(c);
+ }
+
+ /**
+ * Returns the public credentials associated with this {@code Subject}.
+ *
+ * @return the public credentials associated with this {@code Subject}.
+ */
+ public Set<Object> getPublicCredentials() {
+ return publicCredentials;
+ }
+
+
+ /**
+ * Returns this {@code Subject}'s public credentials which are a subclass of
+ * the {@code Class} provided.
+ *
+ * @param c
+ * the {@code Class} as a criteria which the public credentials
+ * returned must satisfy.
+ * @return this {@code Subject}'s public credentials. Modifications to the
+ * returned set of credentials do not affect this {@code Subject}'s
+ * credentials.
+ */
+ public <T> Set<T> getPublicCredentials(Class<T> c) {
+ return publicCredentials.get(c);
+ }
+
+ /**
+ * Returns a hash code of this {@code Subject}.
+ *
+ * @return a hash code of this {@code Subject}.
+ */
+ @Override
+ public int hashCode() {
+ return principals.hashCode() + privateCredentials.hashCode()
+ + publicCredentials.hashCode();
+ }
+
+ /**
+ * Prevents from modifications being done to the credentials and {@link
+ * Principal} sets. After setting it to read-only this {@code Subject} can
+ * not be made writable again. The destroy method on the credentials still
+ * works though.
+ */
+ public void setReadOnly() {
+ checkPermission(_READ_ONLY);
+
+ readOnly = true;
+ }
+
+ /**
+ * Returns whether this {@code Subject} is read-only or not.
+ *
+ * @return whether this {@code Subject} is read-only or not.
+ */
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ /**
+ * Returns a {@code String} representation of this {@code Subject}.
+ *
+ * @return a {@code String} representation of this {@code Subject}.
+ */
+ @Override
+ public String toString() {
+
+ StringBuilder buf = new StringBuilder("Subject:\n"); //$NON-NLS-1$
+
+ Iterator<?> it = principals.iterator();
+ while (it.hasNext()) {
+ buf.append("\tPrincipal: "); //$NON-NLS-1$
+ buf.append(it.next());
+ buf.append('\n');
+ }
+
+ it = publicCredentials.iterator();
+ while (it.hasNext()) {
+ buf.append("\tPublic Credential: "); //$NON-NLS-1$
+ buf.append(it.next());
+ buf.append('\n');
+ }
+
+ int offset = buf.length() - 1;
+ it = privateCredentials.iterator();
+ try {
+ while (it.hasNext()) {
+ buf.append("\tPrivate Credential: "); //$NON-NLS-1$
+ buf.append(it.next());
+ buf.append('\n');
+ }
+ } catch (SecurityException e) {
+ buf.delete(offset, buf.length());
+ buf.append("\tPrivate Credentials: no accessible information\n"); //$NON-NLS-1$
+ }
+ return buf.toString();
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+
+ in.defaultReadObject();
+
+ publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
+ privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Returns the {@code Subject} that was last associated with the {@code
+ * context} provided as argument.
+ *
+ * @param context
+ * the {@code context} that was associated with the
+ * {@code Subject}.
+ * @return the {@code Subject} that was last associated with the {@code
+ * context} provided as argument.
+ */
+ public static Subject getSubject(final AccessControlContext context) {
+ checkPermission(_SUBJECT);
+ if (context == null) {
+ throw new NullPointerException("auth.09"); //$NON-NLS-1$
+ }
+ PrivilegedAction<DomainCombiner> action = new PrivilegedAction<DomainCombiner>() {
+ public DomainCombiner run() {
+ return context.getDomainCombiner();
+ }
+ };
+ DomainCombiner combiner = AccessController.doPrivileged(action);
+
+ if ((combiner == null) || !(combiner instanceof SubjectDomainCombiner)) {
+ return null;
+ }
+ return ((SubjectDomainCombiner) combiner).getSubject();
+ }
+
+ // checks passed permission
+ private static void checkPermission(Permission p) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(p);
+ }
+ }
+
+ // FIXME is used only in two places. remove?
+ private void checkState() {
+ if (readOnly) {
+ throw new IllegalStateException("auth.0A"); //$NON-NLS-1$
+ }
+ }
+
+ private final class SecureSet<SST> extends AbstractSet<SST> implements Serializable {
+
+ /**
+ * Compatibility issue: see comments for setType variable
+ */
+ private static final long serialVersionUID = 7911754171111800359L;
+
+ private LinkedList<SST> elements;
+
+ /*
+ * Is used to define a set type for serialization.
+ *
+ * A type can be principal, priv. or pub. credential set. The spec.
+ * doesn't clearly says that priv. and pub. credential sets can be
+ * serialized and what classes they are. It is only possible to figure
+ * out from writeObject method comments that priv. credential set is
+ * serializable and it is an instance of SecureSet class. So pub.
+ * credential was implemented by analogy
+ *
+ * Compatibility issue: the class follows its specified serial form.
+ * Also according to the serialization spec. adding new field is a
+ * compatible change. So is ok for principal set (because the default
+ * value for integer is zero). But priv. or pub. credential set it is
+ * not compatible because most probably other implementations resolve
+ * this issue in other way
+ */
+ private int setType;
+
+ // Defines principal set for serialization.
+ private static final int SET_Principal = 0;
+
+ // Defines private credential set for serialization.
+ private static final int SET_PrivCred = 1;
+
+ // Defines public credential set for serialization.
+ private static final int SET_PubCred = 2;
+
+ // permission required to modify set
+ private transient AuthPermission permission;
+
+ protected SecureSet(AuthPermission perm) {
+ permission = perm;
+ elements = new LinkedList<SST>();
+ }
+
+ // creates set from specified collection with specified permission
+ // all collection elements are verified before adding
+ protected SecureSet(AuthPermission perm, Collection<? extends SST> s) {
+ this(perm);
+
+ // Subject's constructor receives a Set, we can trusts if a set is from bootclasspath,
+ // and not to check whether it contains duplicates or not
+ boolean trust = s.getClass().getClassLoader() == null;
+
+ Iterator<? extends SST> it = s.iterator();
+ while (it.hasNext()) {
+ SST o = it.next();
+ verifyElement(o);
+ if (trust || !elements.contains(o)) {
+ elements.add(o);
+ }
+ }
+ }
+
+ // verifies new set element
+ private void verifyElement(Object o) {
+
+ if (o == null) {
+ throw new NullPointerException();
+ }
+ if (permission == _PRINCIPALS && !(Principal.class.isAssignableFrom(o.getClass()))) {
+ throw new IllegalArgumentException("auth.0B"); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * verifies specified element, checks set state, and security permission
+ * to modify set before adding new element
+ */
+ @Override
+ public boolean add(SST o) {
+
+ verifyElement(o);
+
+ checkState();
+ checkPermission(permission);
+
+ if (!elements.contains(o)) {
+ elements.add(o);
+ return true;
+ }
+ return false;
+ }
+
+ // returns an instance of SecureIterator
+ @Override
+ public Iterator<SST> iterator() {
+
+ if (permission == _PRIVATE_CREDENTIALS) {
+ /*
+ * private credential set requires iterator with additional
+ * security check (PrivateCredentialPermission)
+ */
+ return new SecureIterator(elements.iterator()) {
+ /*
+ * checks permission to access next private credential moves
+ * to the next element even SecurityException was thrown
+ */
+ @Override
+ public SST next() {
+ SST obj = iterator.next();
+ checkPermission(new PrivateCredentialPermission(obj
+ .getClass().getName(), principals));
+ return obj;
+ }
+ };
+ }
+ return new SecureIterator(elements.iterator());
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+
+ if (c == null) {
+ throw new NullPointerException();
+ }
+ return super.retainAll(c);
+ }
+
+ @Override
+ public int size() {
+ return elements.size();
+ }
+
+ /**
+ * return set with elements that are instances or subclasses of the
+ * specified class
+ */
+ protected final <E> Set<E> get(final Class<E> c) {
+
+ if (c == null) {
+ throw new NullPointerException();
+ }
+
+ AbstractSet<E> s = new AbstractSet<E>() {
+ private LinkedList<E> elements = new LinkedList<E>();
+
+ @Override
+ public boolean add(E o) {
+
+ if (!c.isAssignableFrom(o.getClass())) {
+ throw new IllegalArgumentException(
+ "auth.0C " + c.getName()); //$NON-NLS-1$
+ }
+
+ if (elements.contains(o)) {
+ return false;
+ }
+ elements.add(o);
+ return true;
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return elements.iterator();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+
+ if (c == null) {
+ throw new NullPointerException();
+ }
+ return super.retainAll(c);
+ }
+
+ @Override
+ public int size() {
+ return elements.size();
+ }
+ };
+
+ // FIXME must have permissions for requested priv. credentials
+ for (Iterator<SST> it = iterator(); it.hasNext();) {
+ SST o = it.next();
+ if (c.isAssignableFrom(o.getClass())) {
+ s.add(c.cast(o));
+ }
+ }
+ return s;
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ in.defaultReadObject();
+
+ switch (setType) {
+ case SET_Principal:
+ permission = _PRINCIPALS;
+ break;
+ case SET_PrivCred:
+ permission = _PRIVATE_CREDENTIALS;
+ break;
+ case SET_PubCred:
+ permission = _PUBLIC_CREDENTIALS;
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+
+ Iterator<SST> it = elements.iterator();
+ while (it.hasNext()) {
+ verifyElement(it.next());
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ if (permission == _PRIVATE_CREDENTIALS) {
+ // does security check for each private credential
+ for (Iterator<SST> it = iterator(); it.hasNext();) {
+ it.next();
+ }
+ setType = SET_PrivCred;
+ } else if (permission == _PRINCIPALS) {
+ setType = SET_Principal;
+ } else {
+ setType = SET_PubCred;
+ }
+
+ out.defaultWriteObject();
+ }
+
+ /**
+ * Represents iterator for subject's secure set
+ */
+ private class SecureIterator implements Iterator<SST> {
+ protected Iterator<SST> iterator;
+
+ protected SecureIterator(Iterator<SST> iterator) {
+ this.iterator = iterator;
+ }
+
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ public SST next() {
+ return iterator.next();
+ }
+
+ /**
+ * checks set state, and security permission to modify set before
+ * removing current element
+ */
+ public void remove() {
+ checkState();
+ checkPermission(permission);
+ iterator.remove();
+ }
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/SubjectDomainCombiner.java b/src/org/apache/harmony/javax/security/auth/SubjectDomainCombiner.java
new file mode 100644
index 0000000..edbb672
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/SubjectDomainCombiner.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth;
+
+import java.security.DomainCombiner;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.util.Set;
+
+/**
+ * Merges permissions based on code source and code signers with permissions
+ * granted to the specified {@link Subject}.
+ */
+public class SubjectDomainCombiner implements DomainCombiner {
+
+ // subject to be associated
+ private Subject subject;
+
+ // permission required to get a subject object
+ private static final AuthPermission _GET = new AuthPermission(
+ "getSubjectFromDomainCombiner"); //$NON-NLS-1$
+
+ /**
+ * Creates a domain combiner for the entity provided in {@code subject}.
+ *
+ * @param subject
+ * the entity to which this domain combiner is associated.
+ */
+ public SubjectDomainCombiner(Subject subject) {
+ super();
+ if (subject == null) {
+ throw new NullPointerException();
+ }
+ this.subject = subject;
+ }
+
+ /**
+ * Returns the entity to which this domain combiner is associated.
+ *
+ * @return the entity to which this domain combiner is associated.
+ */
+ public Subject getSubject() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(_GET);
+ }
+
+ return subject;
+ }
+
+ /**
+ * Merges the {@code ProtectionDomain} with the {@code Principal}s
+ * associated with the subject of this {@code SubjectDomainCombiner}.
+ *
+ * @param currentDomains
+ * the {@code ProtectionDomain}s associated with the context of
+ * the current thread. The domains must be sorted according to
+ * the execution order, the most recent residing at the
+ * beginning.
+ * @param assignedDomains
+ * the {@code ProtectionDomain}s from the parent thread based on
+ * code source and signers.
+ * @return a single {@code ProtectionDomain} array computed from the two
+ * provided arrays, or {@code null}.
+ * @see ProtectionDomain
+ */
+ public ProtectionDomain[] combine(ProtectionDomain[] currentDomains,
+ ProtectionDomain[] assignedDomains) {
+ // get array length for combining protection domains
+ int len = 0;
+ if (currentDomains != null) {
+ len += currentDomains.length;
+ }
+ if (assignedDomains != null) {
+ len += assignedDomains.length;
+ }
+ if (len == 0) {
+ return null;
+ }
+
+ ProtectionDomain[] pd = new ProtectionDomain[len];
+
+ // for each current domain substitute set of principal with subject's
+ int cur = 0;
+ if (currentDomains != null) {
+
+ Set<Principal> s = subject.getPrincipals();
+ Principal[] p = s.toArray(new Principal[s.size()]);
+
+ for (cur = 0; cur < currentDomains.length; cur++) {
+ if (currentDomains[cur] != null) {
+ ProtectionDomain newPD;
+ newPD = new ProtectionDomain(currentDomains[cur].getCodeSource(),
+ currentDomains[cur].getPermissions(), currentDomains[cur]
+ .getClassLoader(), p);
+ pd[cur] = newPD;
+ }
+ }
+ }
+
+ // copy assigned domains
+ if (assignedDomains != null) {
+ System.arraycopy(assignedDomains, 0, pd, cur, assignedDomains.length);
+ }
+
+ return pd;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/Callback.java b/src/org/apache/harmony/javax/security/auth/callback/Callback.java
new file mode 100644
index 0000000..8fd745c
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/Callback.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+/**
+ * Defines an empty base interface for all {@code Callback}s used during
+ * authentication.
+ */
+public interface Callback {
+} \ No newline at end of file
diff --git a/src/org/apache/harmony/javax/security/auth/callback/CallbackHandler.java b/src/org/apache/harmony/javax/security/auth/callback/CallbackHandler.java
new file mode 100644
index 0000000..d09fafa
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/CallbackHandler.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.IOException;
+
+/**
+ * Needs to be implemented by classes that want to handle authentication
+ * {@link Callback}s. A single method {@link #handle(Callback[])} must be
+ * provided that checks the type of the incoming {@code Callback}s and reacts
+ * accordingly. {@code CallbackHandler}s can be installed per application. It is
+ * also possible to configure a system-default {@code CallbackHandler} by
+ * setting the {@code auth.login.defaultCallbackHandler} property in the
+ * standard {@code security.properties} file.
+ */
+public interface CallbackHandler {
+
+ /**
+ * Handles the actual {@link Callback}. A {@code CallbackHandler} needs to
+ * implement this method. In the method, it is free to select which {@code
+ * Callback}s it actually wants to handle and in which way. For example, a
+ * console-based {@code CallbackHandler} might choose to sequentially ask
+ * the user for login and password, if it implements these {@code Callback}
+ * s, whereas a GUI-based one might open a single dialog window for both
+ * values. If a {@code CallbackHandler} is not able to handle a specific
+ * {@code Callback}, it needs to throw an
+ * {@link UnsupportedCallbackException}.
+ *
+ * @param callbacks
+ * the array of {@code Callback}s that need handling
+ * @throws IOException
+ * if an I/O related error occurs
+ * @throws UnsupportedCallbackException
+ * if the {@code CallbackHandler} is not able to handle a
+ * specific {@code Callback}
+ */
+ void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException;
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/ChoiceCallback.java b/src/org/apache/harmony/javax/security/auth/callback/ChoiceCallback.java
new file mode 100644
index 0000000..1e53fb6
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/ChoiceCallback.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+
+
+
+public class ChoiceCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = -3975664071579892167L;
+
+ private int defaultChoice;
+
+ private String prompt;
+
+ private boolean multipleSelectionsAllowed;
+
+ private String[] choices;
+
+ private int[] selections;
+
+ private void setChoices(String[] choices) {
+ if (choices == null || choices.length == 0) {
+ throw new IllegalArgumentException("auth.1C"); //$NON-NLS-1$
+ }
+ for (int i = 0; i < choices.length; i++) {
+ if (choices[i] == null || choices[i].length() == 0) {
+ throw new IllegalArgumentException("auth.1C"); //$NON-NLS-1$
+ }
+ }
+ //FIXME: System.arraycopy(choices, 0 , new String[choices.length], 0, choices.length);
+ this.choices = choices;
+
+ }
+
+ private void setPrompt(String prompt) {
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ }
+
+ private void setDefaultChoice(int defaultChoice) {
+ if (0 > defaultChoice || defaultChoice >= choices.length) {
+ throw new IllegalArgumentException("auth.1D"); //$NON-NLS-1$
+ }
+ this.defaultChoice = defaultChoice;
+ }
+
+ public ChoiceCallback(String prompt, String[] choices, int defaultChoice,
+ boolean multipleSelectionsAllowed) {
+ super();
+ setPrompt(prompt);
+ setChoices(choices);
+ setDefaultChoice(defaultChoice);
+ this.multipleSelectionsAllowed = multipleSelectionsAllowed;
+ }
+
+ public boolean allowMultipleSelections() {
+ return multipleSelectionsAllowed;
+ }
+
+ public String[] getChoices() {
+ return choices;
+ }
+
+ public int getDefaultChoice() {
+ return defaultChoice;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public int[] getSelectedIndexes() {
+ return selections;
+ }
+
+ public void setSelectedIndex(int selection) {
+ this.selections = new int[1];
+ this.selections[0] = selection;
+ }
+
+ public void setSelectedIndexes(int[] selections) {
+ if (!multipleSelectionsAllowed) {
+ throw new UnsupportedOperationException();
+ }
+ this.selections = selections;
+ //FIXME:
+ // this.selections = new int[selections.length]
+ //System.arraycopy(selections, 0, this.selections, 0, this.selections.length);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/ConfirmationCallback.java b/src/org/apache/harmony/javax/security/auth/callback/ConfirmationCallback.java
new file mode 100644
index 0000000..a1893f3
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/ConfirmationCallback.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+
+
+
+public class ConfirmationCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = -9095656433782481624L;
+
+ public static final int YES = 0; // default options
+
+ public static final int NO = 1;
+
+ public static final int CANCEL = 2;
+
+ public static final int OK = 3;
+
+ public static final int YES_NO_OPTION = 0; // options type
+
+ public static final int YES_NO_CANCEL_OPTION = 1;
+
+ public static final int OK_CANCEL_OPTION = 2;
+
+ public static final int UNSPECIFIED_OPTION = -1;
+
+ public static final int INFORMATION = 0; // messages type
+
+ public static final int WARNING = 1;
+
+ public static final int ERROR = 2;
+
+ private String prompt;
+
+ private int messageType;
+
+ private int optionType = UNSPECIFIED_OPTION;
+
+ private int defaultOption;
+
+ private String[] options;
+
+ private int selection;
+
+ public ConfirmationCallback(int messageType, int optionType, int defaultOption) {
+ super();
+ if (messageType > ERROR || messageType < INFORMATION) {
+ throw new IllegalArgumentException("auth.16"); //$NON-NLS-1$
+ }
+
+ switch (optionType) {
+ case YES_NO_OPTION:
+ if (defaultOption != YES && defaultOption != NO) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ case YES_NO_CANCEL_OPTION:
+ if (defaultOption != YES && defaultOption != NO && defaultOption != CANCEL) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ case OK_CANCEL_OPTION:
+ if (defaultOption != OK && defaultOption != CANCEL) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("auth.18"); //$NON-NLS-1$
+ }
+ this.messageType = messageType;
+ this.optionType = optionType;
+ this.defaultOption = defaultOption;
+ }
+
+ public ConfirmationCallback(int messageType, String[] options, int defaultOption) {
+ super();
+ if (messageType > ERROR || messageType < INFORMATION) {
+ throw new IllegalArgumentException("auth.16"); //$NON-NLS-1$
+ }
+
+ if (options == null || options.length == 0) {
+ throw new IllegalArgumentException("auth.1A"); //$NON-NLS-1$
+ }
+ for (int i = 0; i < options.length; i++) {
+ if (options[i] == null || options[i].length() == 0) {
+ throw new IllegalArgumentException("auth.1A"); //$NON-NLS-1$
+ }
+ }
+ if (0 > defaultOption || defaultOption >= options.length) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ // FIXME:System.arraycopy(options, 0 , new String[this.options.length],
+ // 0, this.options.length);
+ this.options = options;
+ this.defaultOption = defaultOption;
+ this.messageType = messageType;
+ }
+
+ public ConfirmationCallback(String prompt, int messageType, int optionType,
+ int defaultOption) {
+ super();
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+
+ if (messageType > ERROR || messageType < INFORMATION) {
+ throw new IllegalArgumentException("auth.16"); //$NON-NLS-1$
+ }
+
+ switch (optionType) {
+ case YES_NO_OPTION:
+ if (defaultOption != YES && defaultOption != NO) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ case YES_NO_CANCEL_OPTION:
+ if (defaultOption != YES && defaultOption != NO && defaultOption != CANCEL) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ case OK_CANCEL_OPTION:
+ if (defaultOption != OK && defaultOption != CANCEL) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("auth.18"); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ this.messageType = messageType;
+ this.optionType = optionType;
+ this.defaultOption = defaultOption;
+ }
+
+ public ConfirmationCallback(String prompt, int messageType, String[] options,
+ int defaultOption) {
+ super();
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+
+ if (messageType > ERROR || messageType < INFORMATION) {
+ throw new IllegalArgumentException("auth.16"); //$NON-NLS-1$
+ }
+
+ if (options == null || options.length == 0) {
+ throw new IllegalArgumentException("auth.1A"); //$NON-NLS-1$
+ }
+ for (int i = 0; i < options.length; i++) {
+ if (options[i] == null || options[i].length() == 0) {
+ throw new IllegalArgumentException("auth.1A"); //$NON-NLS-1$
+ }
+ }
+ if (0 > defaultOption || defaultOption >= options.length) {
+ throw new IllegalArgumentException("auth.17"); //$NON-NLS-1$
+ }
+ // FIXME:System.arraycopy(options, 0 , new String[this.options.length],
+ // 0, this.options.length);
+ this.options = options;
+ this.defaultOption = defaultOption;
+ this.messageType = messageType;
+ this.prompt = prompt;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public int getMessageType() {
+ return messageType;
+ }
+
+ public int getDefaultOption() {
+ return defaultOption;
+ }
+
+ public String[] getOptions() {
+ return options;
+ }
+
+ public int getOptionType() {
+ return optionType;
+ }
+
+ public int getSelectedIndex() {
+ return selection;
+ }
+
+ public void setSelectedIndex(int selection) {
+ if (options != null) {
+ if (0 <= selection && selection <= options.length) {
+ this.selection = selection;
+ } else {
+ throw new ArrayIndexOutOfBoundsException("auth.1B"); //$NON-NLS-1$
+ }
+ } else {
+ switch (optionType) {
+ case YES_NO_OPTION:
+ if (selection != YES && selection != NO) {
+ throw new IllegalArgumentException("auth.19"); //$NON-NLS-1$
+ }
+ break;
+ case YES_NO_CANCEL_OPTION:
+ if (selection != YES && selection != NO && selection != CANCEL) {
+ throw new IllegalArgumentException("auth.19"); //$NON-NLS-1$
+ }
+ break;
+ case OK_CANCEL_OPTION:
+ if (selection != OK && selection != CANCEL) {
+ throw new IllegalArgumentException("auth.19"); //$NON-NLS-1$
+ }
+ break;
+ }
+ this.selection = selection;
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/LanguageCallback.java b/src/org/apache/harmony/javax/security/auth/callback/LanguageCallback.java
new file mode 100644
index 0000000..729bb49
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/LanguageCallback.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+public class LanguageCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = 2019050433478903213L;
+
+ private Locale locale;
+
+ public LanguageCallback() {
+ super();
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/NameCallback.java b/src/org/apache/harmony/javax/security/auth/callback/NameCallback.java
new file mode 100644
index 0000000..97264ef
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/NameCallback.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+
+
+
+public class NameCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = 3770938795909392253L;
+
+ private String prompt;
+
+ private String defaultName;
+
+ private String inputName;
+
+ private void setPrompt(String prompt) {
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ }
+
+ private void setDefaultName(String defaultName) {
+ if (defaultName == null || defaultName.length() == 0) {
+ throw new IllegalArgumentException("auth.1E"); //$NON-NLS-1$
+ }
+ this.defaultName = defaultName;
+ }
+
+ public NameCallback(String prompt) {
+ super();
+ setPrompt(prompt);
+ }
+
+ public NameCallback(String prompt, String defaultName) {
+ super();
+ setPrompt(prompt);
+ setDefaultName(defaultName);
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public String getDefaultName() {
+ return defaultName;
+ }
+
+ public void setName(String name) {
+ this.inputName = name;
+ }
+
+ public String getName() {
+ return inputName;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/PasswordCallback.java b/src/org/apache/harmony/javax/security/auth/callback/PasswordCallback.java
new file mode 100644
index 0000000..bd142fc
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/PasswordCallback.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+
+
+/**
+ * Is used in conjunction with a {@link CallbackHandler} to retrieve a password
+ * when needed.
+ */
+public class PasswordCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = 2267422647454909926L;
+
+ private String prompt;
+
+ boolean echoOn;
+
+ private char[] inputPassword;
+
+ private void setPrompt(String prompt) throws IllegalArgumentException {
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ }
+
+ /**
+ * Creates a new {@code PasswordCallback} instance.
+ *
+ * @param prompt
+ * the message that should be displayed to the user
+ * @param echoOn
+ * determines whether the user input should be echoed
+ */
+ public PasswordCallback(String prompt, boolean echoOn) {
+ super();
+ setPrompt(prompt);
+ this.echoOn = echoOn;
+ }
+
+ /**
+ * Returns the prompt that was specified when creating this {@code
+ * PasswordCallback}
+ *
+ * @return the prompt
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Queries whether this {@code PasswordCallback} expects user input to be
+ * echoed, which is specified during the creation of the object.
+ *
+ * @return {@code true} if (and only if) user input should be echoed
+ */
+ public boolean isEchoOn() {
+ return echoOn;
+ }
+
+ /**
+ * Sets the password. The {@link CallbackHandler} that performs the actual
+ * provisioning or input of the password needs to call this method to hand
+ * back the password to the security service that requested it.
+ *
+ * @param password
+ * the password. A copy of this is stored, so subsequent changes
+ * to the input array do not affect the {@code PasswordCallback}.
+ */
+ public void setPassword(char[] password) {
+ if (password == null) {
+ this.inputPassword = password;
+ } else {
+ inputPassword = new char[password.length];
+ System.arraycopy(password, 0, inputPassword, 0, inputPassword.length);
+ }
+ }
+
+ /**
+ * Returns the password. The security service that needs the password
+ * usually calls this method once the {@link CallbackHandler} has finished
+ * its work.
+ *
+ * @return the password. A copy of the internal password is created and
+ * returned, so subsequent changes to the internal password do not
+ * affect the result.
+ */
+ public char[] getPassword() {
+ if (inputPassword != null) {
+ char[] tmp = new char[inputPassword.length];
+ System.arraycopy(inputPassword, 0, tmp, 0, tmp.length);
+ return tmp;
+ }
+ return null;
+ }
+
+ /**
+ * Clears the password stored in this {@code PasswordCallback}.
+ */
+ public void clearPassword() {
+ if (inputPassword != null) {
+ Arrays.fill(inputPassword, '\u0000');
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/TextInputCallback.java b/src/org/apache/harmony/javax/security/auth/callback/TextInputCallback.java
new file mode 100644
index 0000000..c7de222
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/TextInputCallback.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+
+
+
+public class TextInputCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = -8064222478852811804L;
+
+ private String defaultText;
+
+ private String prompt;
+
+ private String inputText;
+
+ private void setPrompt(String prompt) {
+ if (prompt == null || prompt.length() == 0) {
+ throw new IllegalArgumentException("auth.14"); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ }
+
+ private void setDefaultText(String defaultText) {
+ if (defaultText == null || defaultText.length() == 0) {
+ throw new IllegalArgumentException("auth.15"); //$NON-NLS-1$
+ }
+ this.defaultText = defaultText;
+ }
+
+ public TextInputCallback(String prompt) {
+ super();
+ setPrompt(prompt);
+ }
+
+ public TextInputCallback(String prompt, String defaultText) {
+ super();
+ setPrompt(prompt);
+ setDefaultText(defaultText);
+ }
+
+ public String getDefaultText() {
+ return defaultText;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public String getText() {
+ return inputText;
+ }
+
+ public void setText(String text) {
+ this.inputText = text;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/TextOutputCallback.java b/src/org/apache/harmony/javax/security/auth/callback/TextOutputCallback.java
new file mode 100644
index 0000000..23a72fa
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/TextOutputCallback.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+import java.io.Serializable;
+
+
+
+public class TextOutputCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = 1689502495511663102L;
+
+ public static final int INFORMATION = 0;
+
+ public static final int WARNING = 1;
+
+ public static final int ERROR = 2;
+
+ private String message;
+
+ private int messageType;
+
+ public TextOutputCallback(int messageType, String message) {
+ if (messageType > ERROR || messageType < INFORMATION) {
+ throw new IllegalArgumentException("auth.16"); //$NON-NLS-1$
+ }
+ if (message == null || message.length() == 0) {
+ throw new IllegalArgumentException("auth.1F"); //$NON-NLS-1$
+ }
+ this.messageType = messageType;
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public int getMessageType() {
+ return messageType;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/callback/UnsupportedCallbackException.java b/src/org/apache/harmony/javax/security/auth/callback/UnsupportedCallbackException.java
new file mode 100644
index 0000000..19f6e40
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/callback/UnsupportedCallbackException.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.callback;
+
+/**
+ * Thrown when a {@link CallbackHandler} does not support a particular {@link
+ * Callback}.
+ */
+public class UnsupportedCallbackException extends Exception {
+
+ private static final long serialVersionUID = -6873556327655666839L;
+
+ private Callback callback;
+
+ /**
+ * Creates a new exception instance and initializes it with just the
+ * unsupported {@code Callback}, but no error message.
+ *
+ * @param callback
+ * the {@code Callback}
+ */
+ public UnsupportedCallbackException(Callback callback) {
+ super();
+ this.callback = callback;
+ }
+
+ /**
+ * Creates a new exception instance and initializes it with both the
+ * unsupported {@code Callback} and an error message.
+ *
+ * @param callback
+ * the {@code Callback}
+ * @param message
+ * the error message
+ */
+ public UnsupportedCallbackException(Callback callback, String message) {
+ super(message);
+ this.callback = callback;
+ }
+
+ /**
+ * Returns the unsupported {@code Callback} that triggered this exception.
+ *
+ * @return the {@code Callback}
+ */
+ public Callback getCallback() {
+ return callback;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/AccountException.java b/src/org/apache/harmony/javax/security/auth/login/AccountException.java
new file mode 100644
index 0000000..c86e801
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/AccountException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class AccountException extends LoginException {
+
+ private static final long serialVersionUID = -2112878680072211787L;
+
+ public AccountException() {
+ super();
+ }
+
+ public AccountException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/AccountExpiredException.java b/src/org/apache/harmony/javax/security/auth/login/AccountExpiredException.java
new file mode 100644
index 0000000..1e0ce4d
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/AccountExpiredException.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class AccountExpiredException extends AccountException {
+
+ private static final long serialVersionUID = -6064064890162661560L;
+
+ public AccountExpiredException() {
+ super();
+ }
+
+ public AccountExpiredException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/AccountLockedException.java b/src/org/apache/harmony/javax/security/auth/login/AccountLockedException.java
new file mode 100644
index 0000000..47913a5
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/AccountLockedException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class AccountLockedException extends AccountException {
+
+ private static final long serialVersionUID = 8280345554014066334L;
+
+ public AccountLockedException() {
+ super();
+ }
+
+ public AccountLockedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/AccountNotFoundException.java b/src/org/apache/harmony/javax/security/auth/login/AccountNotFoundException.java
new file mode 100644
index 0000000..8ca9b96
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/AccountNotFoundException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class AccountNotFoundException extends AccountException {
+
+ private static final long serialVersionUID = 1498349563916294614L;
+
+ public AccountNotFoundException() {
+ super();
+ }
+
+ public AccountNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/AppConfigurationEntry.java b/src/org/apache/harmony/javax/security/auth/login/AppConfigurationEntry.java
new file mode 100644
index 0000000..2a735dc
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/AppConfigurationEntry.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+import java.util.Collections;
+import java.util.Map;
+
+
+
+public class AppConfigurationEntry {
+
+ // the login module options
+ private final Map<String, ?> options;
+
+ // the control flag
+ private final AppConfigurationEntry.LoginModuleControlFlag controlFlag;
+
+ // the login module name
+ private final String loginModuleName;
+
+ public AppConfigurationEntry(String loginModuleName,
+ AppConfigurationEntry.LoginModuleControlFlag controlFlag, Map<String, ?> options) {
+
+ if (loginModuleName == null || loginModuleName.length() == 0) {
+ throw new IllegalArgumentException("auth.26"); //$NON-NLS-1$
+ }
+
+ if (controlFlag == null) {
+ throw new IllegalArgumentException("auth.27"); //$NON-NLS-1$
+ }
+
+ if (options == null) {
+ throw new IllegalArgumentException("auth.1A"); //$NON-NLS-1$
+ }
+
+ this.loginModuleName = loginModuleName;
+ this.controlFlag = controlFlag;
+ this.options = Collections.unmodifiableMap(options);
+ }
+
+ public String getLoginModuleName() {
+ return loginModuleName;
+ }
+
+ public LoginModuleControlFlag getControlFlag() {
+ return controlFlag;
+ }
+
+ public Map<java.lang.String, ?> getOptions() {
+ return options;
+ }
+
+ public static class LoginModuleControlFlag {
+
+ // the control flag
+ private final String flag;
+
+ public static final LoginModuleControlFlag REQUIRED = new LoginModuleControlFlag(
+ "LoginModuleControlFlag: required"); //$NON-NLS-1$
+
+ public static final LoginModuleControlFlag REQUISITE = new LoginModuleControlFlag(
+ "LoginModuleControlFlag: requisite"); //$NON-NLS-1$
+
+ public static final LoginModuleControlFlag OPTIONAL = new LoginModuleControlFlag(
+ "LoginModuleControlFlag: optional"); //$NON-NLS-1$
+
+ public static final LoginModuleControlFlag SUFFICIENT = new LoginModuleControlFlag(
+ "LoginModuleControlFlag: sufficient"); //$NON-NLS-1$
+
+ // Creates the LoginModuleControlFlag object with specified a flag
+ private LoginModuleControlFlag(String flag) {
+ this.flag = flag;
+ }
+
+ @Override
+ public String toString() {
+ return flag;
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/Configuration.java b/src/org/apache/harmony/javax/security/auth/login/Configuration.java
new file mode 100644
index 0000000..74c371f
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/Configuration.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+import java.security.AccessController;
+import org.apache.harmony.javax.security.auth.AuthPermission;
+
+public abstract class Configuration {
+
+ // the current configuration
+ private static Configuration configuration;
+
+ // creates a AuthPermission object with a specify property
+ private static final AuthPermission GET_LOGIN_CONFIGURATION = new AuthPermission(
+ "getLoginConfiguration"); //$NON-NLS-1$
+
+ // creates a AuthPermission object with a specify property
+ private static final AuthPermission SET_LOGIN_CONFIGURATION = new AuthPermission(
+ "setLoginConfiguration"); //$NON-NLS-1$
+
+ // Key to security properties, defining default configuration provider.
+ private static final String LOGIN_CONFIGURATION_PROVIDER = "login.configuration.provider"; //$NON-NLS-1$
+
+ protected Configuration() {
+ super();
+ }
+
+ public static Configuration getConfiguration() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(GET_LOGIN_CONFIGURATION);
+ }
+ return getAccessibleConfiguration();
+ }
+
+ /**
+ * Reads name of default configuration provider from security.properties,
+ * loads the class and instantiates the provider.<br> In case of any
+ * exception, wraps it with SecurityException and throws further.
+ */
+ private static final Configuration getDefaultProvider() {
+ return new Configuration() {
+
+ @Override
+ public void refresh() {
+ }
+
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(
+ String applicationName) {
+ return new AppConfigurationEntry[0];
+ }
+ };
+ }
+
+ /**
+ * Shortcut accessor for friendly classes, to skip security checks.
+ * If active configuration was set to <code>null</code>, tries to load a default
+ * provider, so this method never returns <code>null</code>. <br>
+ * This method is synchronized with setConfiguration()
+ */
+ static Configuration getAccessibleConfiguration() {
+ Configuration current = configuration;
+ if (current == null) {
+ synchronized (Configuration.class) {
+ if (configuration == null) {
+ configuration = getDefaultProvider();
+ }
+ return configuration;
+ }
+ }
+ return current;
+ }
+
+ public static void setConfiguration(Configuration configuration) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SET_LOGIN_CONFIGURATION);
+ }
+ Configuration.configuration = configuration;
+ }
+
+ public abstract AppConfigurationEntry[] getAppConfigurationEntry(String applicationName);
+
+ public abstract void refresh();
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/CredentialException.java b/src/org/apache/harmony/javax/security/auth/login/CredentialException.java
new file mode 100644
index 0000000..e74e866
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/CredentialException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class CredentialException extends LoginException {
+
+ private static final long serialVersionUID = -4772893876810601859L;
+
+ public CredentialException() {
+ super();
+ }
+
+ public CredentialException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/CredentialExpiredException.java b/src/org/apache/harmony/javax/security/auth/login/CredentialExpiredException.java
new file mode 100644
index 0000000..3ca3ad7
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/CredentialExpiredException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class CredentialExpiredException extends CredentialException {
+
+ private static final long serialVersionUID = -5344739593859737937L;
+
+ public CredentialExpiredException() {
+ super();
+ }
+
+ public CredentialExpiredException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/CredentialNotFoundException.java b/src/org/apache/harmony/javax/security/auth/login/CredentialNotFoundException.java
new file mode 100644
index 0000000..ffd529f
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/CredentialNotFoundException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class CredentialNotFoundException extends CredentialException {
+
+ private static final long serialVersionUID = -7779934467214319475L;
+
+ public CredentialNotFoundException() {
+ super();
+ }
+
+ public CredentialNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/FailedLoginException.java b/src/org/apache/harmony/javax/security/auth/login/FailedLoginException.java
new file mode 100644
index 0000000..f689d99
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/FailedLoginException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+public class FailedLoginException extends LoginException {
+
+ private static final long serialVersionUID = 802556922354616286L;
+
+ public FailedLoginException() {
+ super();
+ }
+
+ public FailedLoginException(String message) {
+ super(message);
+ }
+
+} \ No newline at end of file
diff --git a/src/org/apache/harmony/javax/security/auth/login/LoginContext.java b/src/org/apache/harmony/javax/security/auth/login/LoginContext.java
new file mode 100644
index 0000000..7d46278
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/LoginContext.java
@@ -0,0 +1,548 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.AccessControlContext;
+import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
+
+import java.security.Security;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.harmony.javax.security.auth.Subject;
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+import org.apache.harmony.javax.security.auth.callback.Callback;
+import org.apache.harmony.javax.security.auth.callback.UnsupportedCallbackException;
+import org.apache.harmony.javax.security.auth.spi.LoginModule;
+import org.apache.harmony.javax.security.auth.AuthPermission;
+
+import org.apache.harmony.javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+
+
+public class LoginContext {
+
+ private static final String DEFAULT_CALLBACK_HANDLER_PROPERTY = "auth.login.defaultCallbackHandler"; //$NON-NLS-1$
+
+ /*
+ * Integer constants which serve as a replacement for the corresponding
+ * LoginModuleControlFlag.* constants. These integers are used later as
+ * index in the arrays - see loginImpl() and logoutImpl() methods
+ */
+ private static final int OPTIONAL = 0;
+
+ private static final int REQUIRED = 1;
+
+ private static final int REQUISITE = 2;
+
+ private static final int SUFFICIENT = 3;
+
+ // Subject to be used for this LoginContext's operations
+ private Subject subject;
+
+ /*
+ * Shows whether the subject was specified by user (true) or was created by
+ * this LoginContext itself (false).
+ */
+ private boolean userProvidedSubject;
+
+ // Shows whether we use installed or user-provided Configuration
+ private boolean userProvidedConfig;
+
+ // An user's AccessControlContext, used when user specifies
+ private AccessControlContext userContext;
+
+ /*
+ * Either a callback handler passed by the user or a wrapper for the user's
+ * specified handler - see init() below.
+ */
+ private CallbackHandler callbackHandler;
+
+ /*
+ * An array which keeps the instantiated and init()-ialized login modules
+ * and their states
+ */
+ private Module[] modules;
+
+ // Stores a shared state
+ private Map<String, ?> sharedState;
+
+ // A context class loader used to load [mainly] LoginModules
+ private ClassLoader contextClassLoader;
+
+ // Shows overall status - whether this LoginContext was successfully logged
+ private boolean loggedIn;
+
+ public LoginContext(String name) throws LoginException {
+ super();
+ init(name, null, null, null);
+ }
+
+ public LoginContext(String name, CallbackHandler cbHandler) throws LoginException {
+ super();
+ if (cbHandler == null) {
+ throw new LoginException("auth.34"); //$NON-NLS-1$
+ }
+ init(name, null, cbHandler, null);
+ }
+
+ public LoginContext(String name, Subject subject) throws LoginException {
+ super();
+ if (subject == null) {
+ throw new LoginException("auth.03"); //$NON-NLS-1$
+ }
+ init(name, subject, null, null);
+ }
+
+ public LoginContext(String name, Subject subject, CallbackHandler cbHandler)
+ throws LoginException {
+ super();
+ if (subject == null) {
+ throw new LoginException("auth.03"); //$NON-NLS-1$
+ }
+ if (cbHandler == null) {
+ throw new LoginException("auth.34"); //$NON-NLS-1$
+ }
+ init(name, subject, cbHandler, null);
+ }
+
+ public LoginContext(String name, Subject subject, CallbackHandler cbHandler,
+ Configuration config) throws LoginException {
+ super();
+ init(name, subject, cbHandler, config);
+ }
+
+ // Does all the machinery needed for the initialization.
+ private void init(String name, Subject subject, final CallbackHandler cbHandler,
+ Configuration config) throws LoginException {
+ userProvidedSubject = (this.subject = subject) != null;
+
+ //
+ // Set config
+ //
+ if (name == null) {
+ throw new LoginException("auth.00"); //$NON-NLS-1$
+ }
+
+ if (config == null) {
+ config = Configuration.getAccessibleConfiguration();
+ } else {
+ userProvidedConfig = true;
+ }
+
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null && !userProvidedConfig) {
+ sm.checkPermission(new AuthPermission("createLoginContext." + name));//$NON-NLS-1$
+ }
+
+ AppConfigurationEntry[] entries = config.getAppConfigurationEntry(name);
+ if (entries == null) {
+ if (sm != null && !userProvidedConfig) {
+ sm.checkPermission(new AuthPermission("createLoginContext.other")); //$NON-NLS-1$
+ }
+ entries = config.getAppConfigurationEntry("other"); //$NON-NLS-1$
+ if (entries == null) {
+ throw new LoginException("auth.35 " + name); //$NON-NLS-1$
+ }
+ }
+
+ modules = new Module[entries.length];
+ for (int i = 0; i < modules.length; i++) {
+ modules[i] = new Module(entries[i]);
+ }
+ //
+ // Set CallbackHandler and this.contextClassLoader
+ //
+
+ /*
+ * as some of the operations to be executed (i.e. get*ClassLoader,
+ * getProperty, class loading) are security-checked, then combine all of
+ * them into a single doPrivileged() call.
+ */
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() throws Exception {
+ // First, set the 'contextClassLoader'
+ contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader == null) {
+ contextClassLoader = ClassLoader.getSystemClassLoader();
+ }
+ // then, checks whether the cbHandler is set
+ if (cbHandler == null) {
+ // well, let's try to find it
+ String klassName = Security
+ .getProperty(DEFAULT_CALLBACK_HANDLER_PROPERTY);
+ if (klassName == null || klassName.length() == 0) {
+ return null;
+ }
+ Class<?> klass = Class.forName(klassName, true, contextClassLoader);
+ callbackHandler = (CallbackHandler) klass.newInstance();
+ } else {
+ callbackHandler = cbHandler;
+ }
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException ex) {
+ Throwable cause = ex.getCause();
+ throw (LoginException) new LoginException("auth.36").initCause(cause);//$NON-NLS-1$
+ }
+
+ if (userProvidedConfig) {
+ userContext = AccessController.getContext();
+ } else if (callbackHandler != null) {
+ userContext = AccessController.getContext();
+ callbackHandler = new ContextedCallbackHandler(callbackHandler);
+ }
+ }
+
+ public Subject getSubject() {
+ if (userProvidedSubject || loggedIn) {
+ return subject;
+ }
+ return null;
+ }
+
+ /**
+ * Warning: calling the method more than once may result in undefined
+ * behaviour if logout() method is not invoked before.
+ */
+ public void login() throws LoginException {
+ PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
+ public Void run() throws LoginException {
+ loginImpl();
+ return null;
+ }
+ };
+ try {
+ if (userProvidedConfig) {
+ AccessController.doPrivileged(action, userContext);
+ } else {
+ AccessController.doPrivileged(action);
+ }
+ } catch (PrivilegedActionException ex) {
+ throw (LoginException) ex.getException();
+ }
+ }
+
+ /**
+ * The real implementation of login() method whose calls are wrapped into
+ * appropriate doPrivileged calls in login().
+ */
+ private void loginImpl() throws LoginException {
+ if (subject == null) {
+ subject = new Subject();
+ }
+
+ if (sharedState == null) {
+ sharedState = new HashMap<String, Object>();
+ }
+
+ // PHASE 1: Calling login()-s
+ Throwable firstProblem = null;
+
+ int[] logged = new int[4];
+ int[] total = new int[4];
+
+ for (Module module : modules) {
+ try {
+ // if a module fails during Class.forName(), then it breaks overall
+ // attempt - see catch() below
+ module.create(subject, callbackHandler, sharedState);
+
+ if (module.module.login()) {
+ ++total[module.getFlag()];
+ ++logged[module.getFlag()];
+ if (module.getFlag() == SUFFICIENT) {
+ break;
+ }
+ }
+ } catch (Throwable ex) {
+ if (firstProblem == null) {
+ firstProblem = ex;
+ }
+ if (module.klass == null) {
+ /*
+ * an exception occurred during class lookup - overall
+ * attempt must fail a little trick: increase the REQUIRED's
+ * number - this will look like a failed REQUIRED module
+ * later, so overall attempt will fail
+ */
+ ++total[REQUIRED];
+ break;
+ }
+ ++total[module.getFlag()];
+ // something happened after the class was loaded
+ if (module.getFlag() == REQUISITE) {
+ // ... and no need to walk down anymore
+ break;
+ }
+ }
+ }
+ // end of PHASE1,
+
+ // Let's decide whether we have either overall success or a total failure
+ boolean fail = true;
+
+ /*
+ * Note: 'failed[xxx]!=0' is not enough to check.
+ *
+ * Use 'logged[xx] != total[xx]' instead. This is because some modules
+ * might not be counted as 'failed' if an exception occurred during
+ * preload()/Class.forName()-ing. But, such modules still get counted in
+ * the total[].
+ */
+
+ // if any REQ* module failed - then it's failure
+ if (logged[REQUIRED] != total[REQUIRED] || logged[REQUISITE] != total[REQUISITE]) {
+ // fail = true;
+ } else {
+ if (total[REQUIRED] == 0 && total[REQUISITE] == 0) {
+ // neither REQUIRED nor REQUISITE was configured.
+ // must have at least one SUFFICIENT or OPTIONAL
+ if (logged[OPTIONAL] != 0 || logged[SUFFICIENT] != 0) {
+ fail = false;
+ }
+ //else { fail = true; }
+ } else {
+ fail = false;
+ }
+ }
+
+ int commited[] = new int[4];
+ // clear it
+ total[0] = total[1] = total[2] = total[3] = 0;
+ if (!fail) {
+ // PHASE 2:
+
+ for (Module module : modules) {
+ if (module.klass != null) {
+ ++total[module.getFlag()];
+ try {
+ module.module.commit();
+ ++commited[module.getFlag()];
+ } catch (Throwable ex) {
+ if (firstProblem == null) {
+ firstProblem = ex;
+ }
+ }
+ }
+ }
+ }
+
+ // need to decide once again
+ fail = true;
+ if (commited[REQUIRED] != total[REQUIRED] || commited[REQUISITE] != total[REQUISITE]) {
+ //fail = true;
+ } else {
+ if (total[REQUIRED] == 0 && total[REQUISITE] == 0) {
+ /*
+ * neither REQUIRED nor REQUISITE was configured. must have at
+ * least one SUFFICIENT or OPTIONAL
+ */
+ if (commited[OPTIONAL] != 0 || commited[SUFFICIENT] != 0) {
+ fail = false;
+ } else {
+ //fail = true;
+ }
+ } else {
+ fail = false;
+ }
+ }
+
+ if (fail) {
+ // either login() or commit() failed. aborting...
+
+ for (Module module : modules) {
+ try {
+ module.module.abort();
+ } catch ( /*LoginException*/Throwable ex) {
+ if (firstProblem == null) {
+ firstProblem = ex;
+ }
+ }
+ }
+ if (firstProblem instanceof PrivilegedActionException
+ && firstProblem.getCause() != null) {
+ firstProblem = firstProblem.getCause();
+ }
+ if (firstProblem instanceof LoginException) {
+ throw (LoginException) firstProblem;
+ }
+ throw (LoginException) new LoginException("auth.37").initCause(firstProblem); //$NON-NLS-1$
+ }
+ loggedIn = true;
+ }
+
+ public void logout() throws LoginException {
+ PrivilegedExceptionAction<Void> action = new PrivilegedExceptionAction<Void>() {
+ public Void run() throws LoginException {
+ logoutImpl();
+ return null;
+ }
+ };
+ try {
+ if (userProvidedConfig) {
+ AccessController.doPrivileged(action, userContext);
+ } else {
+ AccessController.doPrivileged(action);
+ }
+ } catch (PrivilegedActionException ex) {
+ throw (LoginException) ex.getException();
+ }
+ }
+
+ /**
+ * The real implementation of logout() method whose calls are wrapped into
+ * appropriate doPrivileged calls in logout().
+ */
+ private void logoutImpl() throws LoginException {
+ if (subject == null) {
+ throw new LoginException("auth.38"); //$NON-NLS-1$
+ }
+ loggedIn = false;
+ Throwable firstProblem = null;
+ int total = 0;
+ for (Module module : modules) {
+ try {
+ module.module.logout();
+ ++total;
+ } catch (Throwable ex) {
+ if (firstProblem == null) {
+ firstProblem = ex;
+ }
+ }
+ }
+ if (firstProblem != null || total == 0) {
+ if (firstProblem instanceof PrivilegedActionException
+ && firstProblem.getCause() != null) {
+ firstProblem = firstProblem.getCause();
+ }
+ if (firstProblem instanceof LoginException) {
+ throw (LoginException) firstProblem;
+ }
+ throw (LoginException) new LoginException("auth.37").initCause(firstProblem); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * <p>A class that servers as a wrapper for the CallbackHandler when we use
+ * installed Configuration, but not a passed one. See API docs on the
+ * LoginContext.</p>
+ *
+ * <p>Simply invokes the given handler with the given AccessControlContext.</p>
+ */
+ private class ContextedCallbackHandler implements CallbackHandler {
+ private final CallbackHandler hiddenHandlerRef;
+
+ ContextedCallbackHandler(CallbackHandler handler) {
+ super();
+ this.hiddenHandlerRef = handler;
+ }
+
+ public void handle(final Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() throws IOException, UnsupportedCallbackException {
+ hiddenHandlerRef.handle(callbacks);
+ return null;
+ }
+ }, userContext);
+ } catch (PrivilegedActionException ex) {
+ if (ex.getCause() instanceof UnsupportedCallbackException) {
+ throw (UnsupportedCallbackException) ex.getCause();
+ }
+ throw (IOException) ex.getCause();
+ }
+ }
+ }
+
+ /**
+ * A private class that stores an instantiated LoginModule.
+ */
+ private final class Module {
+
+ // An initial info about the module to be used
+ AppConfigurationEntry entry;
+
+ // A mapping of LoginModuleControlFlag onto a simple int constant
+ int flag;
+
+ // The LoginModule itself
+ LoginModule module;
+
+ // A class of the module
+ Class<?> klass;
+
+ Module(AppConfigurationEntry entry) {
+ this.entry = entry;
+ LoginModuleControlFlag flg = entry.getControlFlag();
+ if (flg == LoginModuleControlFlag.OPTIONAL) {
+ flag = OPTIONAL;
+ } else if (flg == LoginModuleControlFlag.REQUISITE) {
+ flag = REQUISITE;
+ } else if (flg == LoginModuleControlFlag.SUFFICIENT) {
+ flag = SUFFICIENT;
+ } else {
+ flag = REQUIRED;
+ //if(flg!=LoginModuleControlFlag.REQUIRED) throw new Error()
+ }
+ }
+
+ int getFlag() {
+ return flag;
+ }
+
+ /**
+ * Loads class of the LoginModule, instantiates it and then calls
+ * initialize().
+ */
+ void create(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState)
+ throws LoginException {
+ String klassName = entry.getLoginModuleName();
+ if (klass == null) {
+ try {
+ klass = Class.forName(klassName, false, contextClassLoader);
+ } catch (ClassNotFoundException ex) {
+ throw (LoginException) new LoginException(
+ "auth.39 " + klassName).initCause(ex); //$NON-NLS-1$
+ }
+ }
+
+ if (module == null) {
+ try {
+ module = (LoginModule) klass.newInstance();
+ } catch (IllegalAccessException ex) {
+ throw (LoginException) new LoginException(
+ "auth.3A " + klassName) //$NON-NLS-1$
+ .initCause(ex);
+ } catch (InstantiationException ex) {
+ throw (LoginException) new LoginException(
+ "auth.3A" + klassName) //$NON-NLS-1$
+ .initCause(ex);
+ }
+ module.initialize(subject, callbackHandler, sharedState, entry.getOptions());
+ }
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/auth/login/LoginException.java b/src/org/apache/harmony/javax/security/auth/login/LoginException.java
new file mode 100644
index 0000000..e9ea566
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/login/LoginException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.login;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Base class for exceptions that are thrown when a login error occurs.
+ */
+public class LoginException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -4679091624035232488L;
+
+ /**
+ * Creates a new exception instance and initializes it with default values.
+ */
+ public LoginException() {
+ super();
+ }
+
+ /**
+ * Creates a new exception instance and initializes it with a given message.
+ *
+ * @param message the error message
+ */
+ public LoginException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/harmony/javax/security/auth/spi/LoginModule.java b/src/org/apache/harmony/javax/security/auth/spi/LoginModule.java
new file mode 100644
index 0000000..3ed9eb2
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/auth/spi/LoginModule.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.auth.spi;
+
+import java.util.Map;
+
+import org.apache.harmony.javax.security.auth.Subject;
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+import org.apache.harmony.javax.security.auth.login.LoginException;
+
+public interface LoginModule {
+
+ void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options);
+
+ boolean login() throws LoginException;
+
+ boolean commit() throws LoginException;
+
+ boolean abort() throws LoginException;
+
+ boolean logout() throws LoginException;
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/AuthenticationException.java b/src/org/apache/harmony/javax/security/sasl/AuthenticationException.java
new file mode 100644
index 0000000..38703ef
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/AuthenticationException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+public class AuthenticationException extends SaslException {
+
+ private static final long serialVersionUID = -3579708765071815007L;
+
+ public AuthenticationException() {
+ super();
+ }
+
+ public AuthenticationException(String detail) {
+ super(detail);
+ }
+
+ public AuthenticationException(String detail, Throwable ex) {
+ super(detail, ex);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/AuthorizeCallback.java b/src/org/apache/harmony/javax/security/sasl/AuthorizeCallback.java
new file mode 100644
index 0000000..2ba90a2
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/AuthorizeCallback.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import java.io.Serializable;
+import org.apache.harmony.javax.security.auth.callback.Callback;
+
+public class AuthorizeCallback implements Callback, Serializable {
+
+ private static final long serialVersionUID = -2353344186490470805L;
+
+ /**
+ * Serialized field for storing authenticationID.
+ */
+ private final String authenticationID;
+
+ /**
+ * Serialized field for storing authorizationID.
+ */
+ private final String authorizationID;
+
+ /**
+ * Serialized field for storing authorizedID.
+ */
+ private String authorizedID;
+
+ /**
+ * Store authorized Serialized field.
+ */
+ private boolean authorized;
+
+ public AuthorizeCallback(String authnID, String authzID) {
+ super();
+ authenticationID = authnID;
+ authorizationID = authzID;
+ authorizedID = authzID;
+ }
+
+ public String getAuthenticationID() {
+ return authenticationID;
+ }
+
+ public String getAuthorizationID() {
+ return authorizationID;
+ }
+
+ public String getAuthorizedID() {
+ return (authorized ? authorizedID : null);
+ }
+
+ public boolean isAuthorized() {
+ return authorized;
+ }
+
+ public void setAuthorized(boolean ok) {
+ authorized = ok;
+ }
+
+ public void setAuthorizedID(String id) {
+ if (id != null) {
+ authorizedID = id;
+ }
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/RealmCallback.java b/src/org/apache/harmony/javax/security/sasl/RealmCallback.java
new file mode 100644
index 0000000..65b5d15
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/RealmCallback.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import org.apache.harmony.javax.security.auth.callback.TextInputCallback;
+
+public class RealmCallback extends TextInputCallback {
+
+ private static final long serialVersionUID = -4342673378785456908L;
+
+ public RealmCallback(String prompt) {
+ super(prompt);
+ }
+
+ public RealmCallback(String prompt, String defaultRealmInfo) {
+ super(prompt, defaultRealmInfo);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/RealmChoiceCallback.java b/src/org/apache/harmony/javax/security/sasl/RealmChoiceCallback.java
new file mode 100644
index 0000000..079ea07
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/RealmChoiceCallback.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import org.apache.harmony.javax.security.auth.callback.ChoiceCallback;
+
+public class RealmChoiceCallback extends ChoiceCallback {
+
+ private static final long serialVersionUID = -8588141348846281332L;
+
+ public RealmChoiceCallback(String prompt, String[] choices, int defaultChoice,
+ boolean multiple) {
+ super(prompt, choices, defaultChoice, multiple);
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/Sasl.java b/src/org/apache/harmony/javax/security/sasl/Sasl.java
new file mode 100644
index 0000000..4d827f8
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/Sasl.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import java.security.Provider;
+import java.security.Security;
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.Iterator;
+
+public class Sasl {
+ // SaslClientFactory service name
+ private static final String CLIENTFACTORYSRV = "SaslClientFactory"; //$NON-NLS-1$
+
+ // SaslServerFactory service name
+ private static final String SERVERFACTORYSRV = "SaslServerFactory"; //$NON-NLS-1$
+
+ public static final String POLICY_NOPLAINTEXT = "javax.security.sasl.policy.noplaintext"; //$NON-NLS-1$
+
+ public static final String POLICY_NOACTIVE = "javax.security.sasl.policy.noactive"; //$NON-NLS-1$
+
+ public static final String POLICY_NODICTIONARY = "javax.security.sasl.policy.nodictionary"; //$NON-NLS-1$
+
+ public static final String POLICY_NOANONYMOUS = "javax.security.sasl.policy.noanonymous"; //$NON-NLS-1$
+
+ public static final String POLICY_FORWARD_SECRECY = "javax.security.sasl.policy.forward"; //$NON-NLS-1$
+
+ public static final String POLICY_PASS_CREDENTIALS = "javax.security.sasl.policy.credentials"; //$NON-NLS-1$
+
+ public static final String MAX_BUFFER = "javax.security.sasl.maxbuffer"; //$NON-NLS-1$
+
+ public static final String RAW_SEND_SIZE = "javax.security.sasl.rawsendsize"; //$NON-NLS-1$
+
+ public static final String REUSE = "javax.security.sasl.reuse"; //$NON-NLS-1$
+
+ public static final String QOP = "javax.security.sasl.qop"; //$NON-NLS-1$
+
+ public static final String STRENGTH = "javax.security.sasl.strength"; //$NON-NLS-1$
+
+ public static final String SERVER_AUTH = "javax.security.sasl.server.authentication"; //$NON-NLS-1$
+
+ // Default public constructor is overridden
+ private Sasl() {
+ super();
+ }
+
+ // Forms new instance of factory
+ private static Object newInstance(String factoryName, Provider prv) throws SaslException {
+ String msg = "auth.31"; //$NON-NLS-1$
+ Object factory;
+ ClassLoader cl = prv.getClass().getClassLoader();
+ if (cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+ try {
+ factory = (Class.forName(factoryName, true, cl)).newInstance();
+ return factory;
+ } catch (IllegalAccessException e) {
+ throw new SaslException(msg + factoryName, e);
+ } catch (ClassNotFoundException e) {
+ throw new SaslException(msg + factoryName, e);
+ } catch (InstantiationException e) {
+ throw new SaslException(msg + factoryName, e);
+ }
+ }
+
+ /**
+ * This method forms the list of SaslClient/SaslServer factories which are
+ * implemented in used providers
+ */
+ private static Collection<?> findFactories(String service) {
+ HashSet<Object> fact = new HashSet<Object>();
+ Provider[] pp = Security.getProviders();
+ if ((pp == null) || (pp.length == 0)) {
+ return fact;
+ }
+ HashSet<String> props = new HashSet<String>();
+ for (int i = 0; i < pp.length; i++) {
+ String prName = pp[i].getName();
+ Enumeration<Object> keys = pp[i].keys();
+ while (keys.hasMoreElements()) {
+ String s = (String) keys.nextElement();
+ if (s.startsWith(service)) {
+ String prop = pp[i].getProperty(s);
+ try {
+ if (props.add(prName.concat(prop))) {
+ fact.add(newInstance(prop, pp[i]));
+ }
+ } catch (SaslException e) {
+ // ignore this factory
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ return fact;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Enumeration<SaslClientFactory> getSaslClientFactories() {
+ Collection<SaslClientFactory> res = (Collection<SaslClientFactory>) findFactories(CLIENTFACTORYSRV);
+ return Collections.enumeration(res);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Enumeration<SaslServerFactory> getSaslServerFactories() {
+ Collection<SaslServerFactory> res = (Collection<SaslServerFactory>) findFactories(SERVERFACTORYSRV);
+ return Collections.enumeration(res);
+ }
+
+ public static SaslServer createSaslServer(String mechanism, String protocol,
+ String serverName, Map<String, ?> prop, CallbackHandler cbh) throws SaslException {
+ if (mechanism == null) {
+ throw new NullPointerException("auth.32"); //$NON-NLS-1$
+ }
+ Collection<?> res = findFactories(SERVERFACTORYSRV);
+ if (res.isEmpty()) {
+ return null;
+ }
+
+ Iterator<?> iter = res.iterator();
+ while (iter.hasNext()) {
+ SaslServerFactory fact = (SaslServerFactory) iter.next();
+ String[] mech = fact.getMechanismNames(null);
+ boolean is = false;
+ if (mech != null) {
+ for (int j = 0; j < mech.length; j++) {
+ if (mech[j].equals(mechanism)) {
+ is = true;
+ break;
+ }
+ }
+ }
+ if (is) {
+ SaslServer saslS = fact.createSaslServer(mechanism, protocol, serverName, prop,
+ cbh);
+ if (saslS != null) {
+ return saslS;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static SaslClient createSaslClient(String[] mechanisms, String authanticationID,
+ String protocol, String serverName, Map<String, ?> prop, CallbackHandler cbh)
+ throws SaslException {
+ if (mechanisms == null) {
+ throw new NullPointerException("auth.33"); //$NON-NLS-1$
+ }
+ Collection<?> res = findFactories(CLIENTFACTORYSRV);
+ if (res.isEmpty()) {
+ return null;
+ }
+
+ Iterator<?> iter = res.iterator();
+ while (iter.hasNext()) {
+ SaslClientFactory fact = (SaslClientFactory) iter.next();
+ String[] mech = fact.getMechanismNames(null);
+ boolean is = false;
+ if (mech != null) {
+ for (int j = 0; j < mech.length; j++) {
+ for (int n = 0; n < mechanisms.length; n++) {
+ if (mech[j].equals(mechanisms[n])) {
+ is = true;
+ break;
+ }
+ }
+ }
+ }
+ if (is) {
+ SaslClient saslC = fact.createSaslClient(mechanisms, authanticationID,
+ protocol, serverName, prop, cbh);
+ if (saslC != null) {
+ return saslC;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/SaslClient.java b/src/org/apache/harmony/javax/security/sasl/SaslClient.java
new file mode 100644
index 0000000..e07ff53
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/SaslClient.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+public interface SaslClient {
+
+ void dispose() throws SaslException;
+
+ byte[] evaluateChallenge(byte[] challenge) throws SaslException;
+
+ String getMechanismName();
+
+ Object getNegotiatedProperty(String propName);
+
+ boolean hasInitialResponse();
+
+ boolean isComplete();
+
+ byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException;
+
+ byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException;
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/SaslClientFactory.java b/src/org/apache/harmony/javax/security/sasl/SaslClientFactory.java
new file mode 100644
index 0000000..e567ed3
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/SaslClientFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import java.util.Map;
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+
+public interface SaslClientFactory {
+
+ SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol,
+ String serverName, Map<String, ?> props, CallbackHandler cbh) throws SaslException;
+
+ String[] getMechanismNames(Map<String, ?> props);
+
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/SaslException.java b/src/org/apache/harmony/javax/security/sasl/SaslException.java
new file mode 100644
index 0000000..1ab7b12
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/SaslException.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import java.io.IOException;
+
+public class SaslException extends IOException {
+
+ private static final long serialVersionUID = 4579784287983423626L;
+
+ /**
+ * Serialized field for storing initial cause
+ */
+ private Throwable _exception;
+
+ public SaslException() {
+ super();
+ }
+
+ public SaslException(String detail) {
+ super(detail);
+ }
+
+ public SaslException(String detail, Throwable ex) {
+ super(detail);
+ if (ex != null) {
+ super.initCause(ex);
+ _exception = ex;
+ }
+ }
+
+ @Override
+ public Throwable getCause() {
+ return _exception;
+ }
+
+ @Override
+ public Throwable initCause(Throwable cause) {
+ super.initCause(cause);
+ _exception = cause;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ if (_exception == null) {
+ return super.toString();
+ }
+ StringBuilder sb = new StringBuilder(super.toString());
+ sb.append(", caused by: "); //$NON-NLS-1$
+ sb.append(_exception.toString());
+ return sb.toString();
+ }
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/SaslServer.java b/src/org/apache/harmony/javax/security/sasl/SaslServer.java
new file mode 100644
index 0000000..f057a4b
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/SaslServer.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+public interface SaslServer {
+
+ void dispose() throws SaslException;
+
+ byte[] evaluateResponse(byte[] response) throws SaslException;
+
+ String getAuthorizationID();
+
+ String getMechanismName();
+
+ Object getNegotiatedProperty(String propName);
+
+ boolean isComplete();
+
+ byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException;
+
+ byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException;
+}
diff --git a/src/org/apache/harmony/javax/security/sasl/SaslServerFactory.java b/src/org/apache/harmony/javax/security/sasl/SaslServerFactory.java
new file mode 100644
index 0000000..d59530e
--- /dev/null
+++ b/src/org/apache/harmony/javax/security/sasl/SaslServerFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.javax.security.sasl;
+
+import java.util.Map;
+import org.apache.harmony.javax.security.auth.callback.CallbackHandler;
+
+public interface SaslServerFactory {
+
+ SaslServer createSaslServer(String mechanisms, String protocol, String serverName,
+ Map<String, ?> props, CallbackHandler cbh) throws SaslException;
+
+ String[] getMechanismNames(Map<String, ?> props);
+
+}