123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*
- * 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;
- /**
- * 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 "PrincipalName"}*
- * </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(Messages.getString("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(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());
- }
- /**
- * 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 "PrincipalName"}*
- * </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(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) {
- 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();
- }
- }
- }
|