summaryrefslogtreecommitdiffstats
path: root/auth/src/main/java/javax/security
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /auth/src/main/java/javax/security
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'auth/src/main/java/javax/security')
-rw-r--r--auth/src/main/java/javax/security/auth/AuthPermission.java52
-rw-r--r--auth/src/main/java/javax/security/auth/DestroyFailedException.java32
-rw-r--r--auth/src/main/java/javax/security/auth/Destroyable.java26
-rw-r--r--auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java333
-rw-r--r--auth/src/main/java/javax/security/auth/Subject.java601
-rw-r--r--auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java90
-rw-r--r--auth/src/main/java/javax/security/auth/callback/Callback.java21
-rw-r--r--auth/src/main/java/javax/security/auth/callback/CallbackHandler.java24
-rw-r--r--auth/src/main/java/javax/security/auth/callback/PasswordCallback.java79
-rw-r--r--auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java39
-rw-r--r--auth/src/main/java/javax/security/auth/callback/package.html15
-rw-r--r--auth/src/main/java/javax/security/auth/login/LoginException.java34
-rw-r--r--auth/src/main/java/javax/security/auth/login/package.html15
-rw-r--r--auth/src/main/java/javax/security/auth/package.html18
-rw-r--r--auth/src/main/java/javax/security/auth/x500/X500Principal.java135
-rw-r--r--auth/src/main/java/javax/security/auth/x500/package.html18
16 files changed, 1532 insertions, 0 deletions
diff --git a/auth/src/main/java/javax/security/auth/AuthPermission.java b/auth/src/main/java/javax/security/auth/AuthPermission.java
new file mode 100644
index 0000000..31f5b50
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/AuthPermission.java
@@ -0,0 +1,52 @@
+/*
+ * 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 javax.security.auth;
+
+import java.security.BasicPermission;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+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(Messages.getString("auth.13")); //$NON-NLS-1$
+ }
+
+ if (CREATE_LOGIN_CONTEXT.equals(name)) {
+ return CREATE_LOGIN_CONTEXT_ANY;
+ }
+ return name;
+ }
+
+ public AuthPermission(String name) {
+ super(init(name));
+ }
+
+ public AuthPermission(String name, String actions) {
+ super(init(name), actions);
+ }
+} \ No newline at end of file
diff --git a/auth/src/main/java/javax/security/auth/DestroyFailedException.java b/auth/src/main/java/javax/security/auth/DestroyFailedException.java
new file mode 100644
index 0000000..16e9dfb
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/DestroyFailedException.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 javax.security.auth;
+
+public class DestroyFailedException extends Exception {
+
+ private static final long serialVersionUID = -7790152857282749162L;
+
+ public DestroyFailedException() {
+ super();
+ }
+
+ public DestroyFailedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/auth/src/main/java/javax/security/auth/Destroyable.java b/auth/src/main/java/javax/security/auth/Destroyable.java
new file mode 100644
index 0000000..a54cbe6
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/Destroyable.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 javax.security.auth;
+
+public interface Destroyable {
+
+ void destroy() throws DestroyFailedException;
+
+ boolean isDestroyed();
+
+}
diff --git a/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java b/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java
new file mode 100644
index 0000000..1f5a560
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java
@@ -0,0 +1,333 @@
+/*
+ * 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 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;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+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;
+
+ public PrivateCredentialPermission(String name, String action) {
+ super(name);
+ if (READ.equalsIgnoreCase(action)) {
+ initTargetName(name);
+ } else {
+ throw new IllegalArgumentException(Messages.getString("auth.11")); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Creates a <code>PrivateCredentialPermission</code> from the Credential Class
+ * and Set of Principals
+ *
+ * @param credentialClass - credential class name
+ * @param principals - principal set
+ */
+ 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(Messages.getString("auth.0E")); //$NON-NLS-1$
+ }
+
+ // check empty string
+ name = name.trim();
+ if (name.length() == 0) {
+ throw new IllegalArgumentException(Messages.getString("auth.0F")); //$NON-NLS-1$
+ }
+
+ // get CredentialClass
+ int beg = name.indexOf(' ');
+ if (beg == -1) {
+ throw new IllegalArgumentException(Messages.getString("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(Messages.getString("auth.10")); //$NON-NLS-1$
+ }
+ }
+
+ // name MUST have one pair at least
+ if (count < 1) {
+ throw new IllegalArgumentException(Messages.getString("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());
+ }
+
+ 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;
+ }
+
+ 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(Messages.getString("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) {
+ return principalClass.equals(((CredOwner) obj).principalClass)
+ && principalName.equals(((CredOwner) obj).principalName);
+ }
+
+ // Returns the hash code value for this object.
+ @Override
+ public int hashCode() {
+ return principalClass.hashCode() + principalName.hashCode();
+ }
+ }
+}
diff --git a/auth/src/main/java/javax/security/auth/Subject.java b/auth/src/main/java/javax/security/auth/Subject.java
new file mode 100644
index 0000000..12c2ff6
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/Subject.java
@@ -0,0 +1,601 @@
+/*
+ * 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 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;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+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;
+
+ public Subject() {
+ super();
+ principals = new SecureSet<Principal>(_PRINCIPALS);
+ publicCredentials = new SecureSet<Object>(_PUBLIC_CREDENTIALS);
+ privateCredentials = new SecureSet<Object>(_PRIVATE_CREDENTIALS);
+
+ readOnly = false;
+ }
+
+ 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;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Object doAs(Subject subject, PrivilegedAction action) {
+
+ checkPermission(_AS);
+
+ return doAs_PrivilegedAction(subject, action, AccessController.getContext());
+ }
+
+ @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);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Object doAs(Subject subject, PrivilegedExceptionAction action)
+ throws PrivilegedActionException {
+
+ checkPermission(_AS);
+
+ return doAs_PrivilegedExceptionAction(subject, action, AccessController.getContext());
+ }
+
+ @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);
+ }
+
+ @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;
+ }
+
+ public Set<Principal> getPrincipals() {
+ return principals;
+ }
+
+ public <T extends Principal> Set<T> getPrincipals(Class<T> c) {
+ return ((SecureSet<Principal>) principals).get(c);
+ }
+
+ public Set<Object> getPrivateCredentials() {
+ return privateCredentials;
+ }
+
+ public <T> Set<T> getPrivateCredentials(Class<T> c) {
+ return privateCredentials.get(c);
+ }
+
+ public Set<Object> getPublicCredentials() {
+ return publicCredentials;
+ }
+
+ public <T> Set<T> getPublicCredentials(Class<T> c) {
+ return publicCredentials.get(c);
+ }
+
+ @Override
+ public int hashCode() {
+ return principals.hashCode() + privateCredentials.hashCode()
+ + publicCredentials.hashCode();
+ }
+
+ public void setReadOnly() {
+ checkPermission(_READ_ONLY);
+
+ readOnly = true;
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ @Override
+ public String toString() {
+
+ StringBuffer buf = new StringBuffer("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();
+ }
+
+ public static Subject getSubject(final AccessControlContext context) {
+ checkPermission(_SUBJECT);
+ if (context == null) {
+ throw new NullPointerException(Messages.getString("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(Messages.getString("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(Messages.getString("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(
+ Messages.getString("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();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java b/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java
new file mode 100644
index 0000000..80f9d85
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java
@@ -0,0 +1,90 @@
+/*
+ * 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 javax.security.auth;
+
+import java.security.DomainCombiner;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.util.Set;
+
+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$
+
+ public SubjectDomainCombiner(Subject subject) {
+ super();
+ if (subject == null) {
+ throw new NullPointerException();
+ }
+ this.subject = subject;
+ }
+
+ public Subject getSubject() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(_GET);
+ }
+
+ return subject;
+ }
+
+ 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++) {
+ 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/auth/src/main/java/javax/security/auth/callback/Callback.java b/auth/src/main/java/javax/security/auth/callback/Callback.java
new file mode 100644
index 0000000..13e7574
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/callback/Callback.java
@@ -0,0 +1,21 @@
+/*
+ * 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 javax.security.auth.callback;
+
+public interface Callback {
+} \ No newline at end of file
diff --git a/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java b/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java
new file mode 100644
index 0000000..ceaeba4
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java
@@ -0,0 +1,24 @@
+/*
+ * 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 javax.security.auth.callback;
+
+public interface CallbackHandler {
+
+ void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
+
+}
diff --git a/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java b/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java
new file mode 100644
index 0000000..e8191bf
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/callback/PasswordCallback.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 javax.security.auth.callback;
+
+import java.io.Serializable;
+import java.util.Arrays;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+
+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(Messages.getString("auth.14")); //$NON-NLS-1$
+ }
+ this.prompt = prompt;
+ }
+
+ public PasswordCallback(String prompt, boolean echoOn) {
+ super();
+ setPrompt(prompt);
+ this.echoOn = echoOn;
+ }
+
+ public String getPrompt() {
+ return prompt;
+ }
+
+ public boolean isEchoOn() {
+ return echoOn;
+ }
+
+ 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);
+ }
+ }
+
+ public char[] getPassword() {
+ if (inputPassword != null) {
+ char[] tmp = new char[inputPassword.length];
+ System.arraycopy(inputPassword, 0, tmp, 0, tmp.length);
+ return tmp;
+ }
+ return null;
+ }
+
+ public void clearPassword() {
+ if (inputPassword != null) {
+ Arrays.fill(inputPassword, '\u0000');
+ }
+ }
+}
diff --git a/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java b/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java
new file mode 100644
index 0000000..e814774
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java
@@ -0,0 +1,39 @@
+/*
+ * 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 javax.security.auth.callback;
+
+public class UnsupportedCallbackException extends Exception {
+
+ private static final long serialVersionUID = -6873556327655666839L;
+
+ private Callback callback;
+
+ public UnsupportedCallbackException(Callback callback) {
+ super();
+ this.callback = callback;
+ }
+
+ public UnsupportedCallbackException(Callback callback, String message) {
+ super(message);
+ this.callback = callback;
+ }
+
+ public Callback getCallback() {
+ return callback;
+ }
+}
diff --git a/auth/src/main/java/javax/security/auth/callback/package.html b/auth/src/main/java/javax/security/auth/callback/package.html
new file mode 100644
index 0000000..50073c7
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/callback/package.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+</head>
+<html>
+<body>
+<p>
+This package provides all the classes and interfaces needed to interact with the application
+in order to execute the authentification and authorization processes.
+It is a classical callback mechanism: one retrieves information (i.e. for authentification
+purposes) and one display some messages (for example error messages).
+
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/auth/src/main/java/javax/security/auth/login/LoginException.java b/auth/src/main/java/javax/security/auth/login/LoginException.java
new file mode 100644
index 0000000..993d5c1
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/login/LoginException.java
@@ -0,0 +1,34 @@
+/*
+ * 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 javax.security.auth.login;
+
+import java.security.GeneralSecurityException;
+
+public class LoginException extends GeneralSecurityException {
+
+ private static final long serialVersionUID = -4679091624035232488L;
+
+ public LoginException() {
+ super();
+ }
+
+ public LoginException(String message) {
+ super(message);
+ }
+
+}
diff --git a/auth/src/main/java/javax/security/auth/login/package.html b/auth/src/main/java/javax/security/auth/login/package.html
new file mode 100644
index 0000000..f8d7ab9
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/login/package.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+</head>
+<html>
+<body>
+<p>
+This package provides a pluggable and stackable authentication system based on ideas and concepts
+from the Unix-PAM module.
+New authentication methods can be specified simply via a new LoginModule and chained together
+with the existing ones.
+
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/auth/src/main/java/javax/security/auth/package.html b/auth/src/main/java/javax/security/auth/package.html
new file mode 100644
index 0000000..3dd5344
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/package.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+</head>
+<html>
+<body>
+<p>
+This package provides all the classes and interfaces needed to implemenet and program
+different methods of users' authentification and role based users' authorization.
+It integrates the previous separated JAAS package into the Java SDK.
+
+All subjects' authentification and role based authorization are strongly coupled with
+the java.security file that, as always, is the ultimate arbiter of all matters secure in Java.
+For example the class {@link javax.security.auth.SubjectDomainCombiner} updates the
+ProtectionDomains associated with the actual class with the subjects defined therein.
+</p>
+</body>
+</html>
diff --git a/auth/src/main/java/javax/security/auth/x500/X500Principal.java b/auth/src/main/java/javax/security/auth/x500/X500Principal.java
new file mode 100644
index 0000000..a168dae
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/x500/X500Principal.java
@@ -0,0 +1,135 @@
+/*
+ * 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 javax.security.auth.x500;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.apache.harmony.auth.internal.nls.Messages;
+import org.apache.harmony.security.x501.Name;
+
+public final class X500Principal implements Serializable, Principal {
+
+ private static final long serialVersionUID = -500463348111345721L;
+
+ public static final String CANONICAL = "CANONICAL"; //$NON-NLS-1$
+
+ public static final String RFC1779 = "RFC1779"; //$NON-NLS-1$
+
+ public static final String RFC2253 = "RFC2253"; //$NON-NLS-1$
+
+ //Distinguished Name
+ private transient Name dn;
+
+ public X500Principal(byte[] name) {
+ super();
+ if (name == null) {
+ throw new IllegalArgumentException(Messages.getString("auth.00")); //$NON-NLS-1$
+ }
+ try {
+ // FIXME dn = new Name(name);
+ dn = (Name) Name.ASN1.decode(name);
+ } catch (IOException e) {
+ IllegalArgumentException iae = new IllegalArgumentException(Messages
+ .getString("auth.2B")); //$NON-NLS-1$
+ iae.initCause(e);
+ throw iae;
+ }
+ }
+
+ public X500Principal(InputStream in) {
+ super();
+ if (in == null) {
+ throw new NullPointerException(Messages.getString("auth.2C")); //$NON-NLS-1$
+ }
+ try {
+ // FIXME dn = new Name(is);
+ dn = (Name) Name.ASN1.decode(in);
+ } catch (IOException e) {
+ IllegalArgumentException iae = new IllegalArgumentException(Messages
+ .getString("auth.2B")); //$NON-NLS-1$
+ iae.initCause(e);
+ throw iae;
+ }
+ }
+
+ public X500Principal(String name) {
+ super();
+ if (name == null) {
+ throw new NullPointerException(Messages.getString("auth.00")); //$NON-NLS-1$
+ }
+ try {
+ dn = new Name(name);
+ } catch (IOException e) {
+ IllegalArgumentException iae = new IllegalArgumentException(Messages
+ .getString("auth.2D")); //$NON-NLS-1$
+ iae.initCause(e);
+ throw iae;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+ X500Principal principal = (X500Principal) o;
+ return dn.getName(CANONICAL).equals(principal.dn.getName(CANONICAL));
+ }
+
+ public byte[] getEncoded() {
+ byte[] src = dn.getEncoded();
+ byte[] dst = new byte[src.length];
+ System.arraycopy(src, 0, dst, 0, dst.length);
+ return dst;
+ }
+
+ public String getName() {
+ return dn.getName(RFC2253);
+ }
+
+ public String getName(String format) {
+ return dn.getName(format);
+ }
+
+ @Override
+ public int hashCode() {
+ return dn.getName(CANONICAL).hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return dn.getName(RFC1779);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.writeObject(dn.getEncoded());
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+
+ dn = (Name) Name.ASN1.decode((byte[]) in.readObject());
+ }
+}
diff --git a/auth/src/main/java/javax/security/auth/x500/package.html b/auth/src/main/java/javax/security/auth/x500/package.html
new file mode 100644
index 0000000..3a7163e
--- /dev/null
+++ b/auth/src/main/java/javax/security/auth/x500/package.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+</head>
+<html>
+<body>
+<p>
+This package provides all the classes needed to store X.500 principals and their credentials.
+The class {@link javax.security.auth.x500.X500Principal} represents such a principal.
+Specifically, X500 principals are defined by such tokens (distinguished names) as O=Google,
+ OU=Android, C=US.
+ The class accepts string representations of distinguished names defined in both
+ specifications RFC2253 and (the older) RFC1779. OID (Object Identifiers used to encode with
+ the ASN.1 standard the extended attributes of distinguished name, algorithm etc.) must
+ follow the RFC2459 specification.
+</p>
+</body>
+</html>