FileDocCategorySizeDatePackage
NameConstraints.javaAPI DocAndroid 1.5 API12339Wed May 06 22:41:06 BST 2009org.apache.harmony.security.x509

NameConstraints

public class NameConstraints extends ExtensionValue
The class encapsulates the ASN.1 DER encoding/decoding work with the following structure which is a part of X.509 certificate (as specified in RFC 3280 - Internet X.509 Public Key Infrastructure. Certificate and Certificate Revocation List (CRL) Profile. http://www.ietf.org/rfc/rfc3280.txt):

NameConstraints ::= SEQUENCE {
permittedSubtrees [0] GeneralSubtrees OPTIONAL,
excludedSubtrees [1] GeneralSubtrees OPTIONAL }

GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree

see
org.apache.harmony.security.x509.GeneralSubtree
see
org.apache.harmony.security.x509.GeneralName

Fields Summary
private final GeneralSubtrees
permittedSubtrees
private final GeneralSubtrees
excludedSubtrees
private byte[]
encoding
private ArrayList[]
permitted_names
private ArrayList[]
excluded_names
public static final org.apache.harmony.security.asn1.ASN1Sequence
ASN1
X.509 NameConstraints encoder/decoder.
Constructors Summary
public NameConstraints()
Default ctor

        this(null, null);
    
public NameConstraints(GeneralSubtrees permittedSubtrees, GeneralSubtrees excludedSubtrees)
Constructs NameConstrains object

param
permittedSubtrees: GeneralSubtrees
param
excludedSubtrees: GeneralSubtrees

        if (permittedSubtrees != null) {
            List ps = permittedSubtrees.getSubtrees();
            if ((ps == null) || (ps.size() == 0)) {
                throw 
                    new IllegalArgumentException(Messages.getString("security.17D")); //$NON-NLS-1$
            }
        }
        if (excludedSubtrees != null) {
            List es = excludedSubtrees.getSubtrees();
            if ((es == null) || (es.size() == 0)) {
                throw 
                    new IllegalArgumentException(Messages.getString("security.17E")); //$NON-NLS-1$
            }
        }
        this.permittedSubtrees = permittedSubtrees;
        this.excludedSubtrees = excludedSubtrees;
    
private NameConstraints(GeneralSubtrees permittedSubtrees, GeneralSubtrees excludedSubtrees, byte[] encoding)

        this(permittedSubtrees, excludedSubtrees);
        this.encoding = encoding;
    
Methods Summary
public static org.apache.harmony.security.x509.NameConstraintsdecode(byte[] encoding)

        return (NameConstraints) ASN1.decode(encoding);
    
public voiddumpValue(java.lang.StringBuffer buffer, java.lang.String prefix)
Places the string representation of extension value into the StringBuffer object.

        buffer.append(prefix).append("Name Constraints: [\n"); //$NON-NLS-1$
        if (permittedSubtrees != null) {
            buffer.append(prefix).append("  Permitted: [\n"); //$NON-NLS-1$
            for (Iterator it=permittedSubtrees.getSubtrees().iterator();
                    it.hasNext();) {
                ((GeneralSubtree) it.next()).dumpValue(buffer, prefix + "    "); //$NON-NLS-1$
            }
            buffer.append(prefix).append("  ]\n"); //$NON-NLS-1$
        }
        if (excludedSubtrees != null) {
            buffer.append(prefix).append("  Excluded: [\n"); //$NON-NLS-1$
            for (Iterator it=excludedSubtrees.getSubtrees().iterator();
                    it.hasNext();) {
                ((GeneralSubtree) it.next()).dumpValue(buffer, prefix + "    "); //$NON-NLS-1$
            }
            buffer.append(prefix).append("  ]\n"); //$NON-NLS-1$
        }
        buffer.append('\n").append(prefix).append("]\n"); //$NON-NLS-1$
    
public byte[]getEncoded()
Returns ASN.1 encoded form of this X.509 NameConstraints value.

return
a byte array containing ASN.1 encode form.

        if (encoding == null) {
            encoding = ASN1.encode(this);
        }
        return encoding;
    
private byte[]getExtensionValue(java.security.cert.X509Certificate cert, java.lang.String OID)

        try {
            byte[] bytes = cert.getExtensionValue(OID);
            if (bytes == null) {
                return null;
            }
            return (byte[]) ASN1OctetString.getInstance().decode(bytes);
        } catch (IOException e) {
            return null;
        }
    
public booleanisAcceptable(java.security.cert.X509Certificate cert)
Apply the name restrictions specified by this NameConstraints instance to the subject distinguished name and subject alternative names of specified X509Certificate. Restrictions apply only if specified name form is present in the certificate. The restrictions are applied according the RFC 3280 (see 4.2.1.11 Name Constraints), excepting that restrictions are applied and to CA certificates, and to certificates which issuer and subject names the same (i.e. method does not check if it CA's certificate or not, or if the names differ or not. This check if it is needed should be done by caller before calling this method).

param
X509Certificate : X.509 Certificate to be checked.
return
true, if the certificate is acceptable according these NameConstraints restrictions, and false otherwise.

        if (permitted_names == null) {
            prepareNames();
        }

        byte[] bytes = getExtensionValue(cert, "2.5.29.17"); //$NON-NLS-1$
        List names;
        try {
            names = (bytes == null) 
                ? new ArrayList(1) // will check the subject field only
                : ((GeneralNames) GeneralNames.ASN1.decode(bytes)).getNames();
        } catch (IOException e) {
            // the certificate is broken;
            e.printStackTrace();
            return false;
        }
        if ((excluded_names[4] != null) || (permitted_names[4] != null)) {
            try {
                names.add(new GeneralName(4, 
                        cert.getSubjectX500Principal().getName()));
            } catch (IOException e) {
                // should never be happened
            }
        }
        return isAcceptable(names);
    
public booleanisAcceptable(java.util.List names)
Check if this list of names is acceptable accoring to this NameConstraints object.

param
names: List
return

        if (permitted_names == null) {
            prepareNames();
        }
        
        Iterator it = names.iterator();
        // check map: shows which types of permitted alternative names are 
        // presented in the certificate
        boolean[] types_presented = new boolean[9];
        // check map: shows if permitted name of presented type is found 
        // among the certificate's alternative names
        boolean[] permitted_found = new boolean[9];
        while (it.hasNext()) {
            GeneralName name = (GeneralName) it.next();
            int type = name.getTag();
            // search the name in excluded names
            if (excluded_names[type] != null) {
                for (int i=0; i<excluded_names[type].size(); i++) {
                    if (((GeneralName) excluded_names[type].get(i))
                            .isAcceptable(name)) {
                        return false;
                    }
                }
            }
            // Search the name in permitted names
            // (if we already found the name of such type between the alt
            // names - we do not need to check others)
            if ((permitted_names[type] != null) && (!permitted_found[type])) {
                types_presented[type] = true;
                for (int i=0; i<permitted_names[type].size(); i++) {
                    if (((GeneralName) permitted_names[type].get(i))
                            .isAcceptable(name)) {
                        // found one permitted name of such type
                        permitted_found[type] = true;
                    }
                }
            }
        }
        for (int type=0; type<9; type++) {
            if (types_presented[type] && !permitted_found[type]) {
                return false;
            }
        }
        return true;
    
private voidprepareNames()

        // array of lists with permitted General Names divided by type
        permitted_names = new ArrayList[9];
        if (permittedSubtrees != null) {
            Iterator it =  permittedSubtrees.getSubtrees().iterator();
            while (it.hasNext()) {
                GeneralName name = ((GeneralSubtree) it.next()).getBase();
                //System.out.println("PERMITTED: "+name);
                int tag = name.getTag();
                if (permitted_names[tag] == null) {
                    permitted_names[tag] = new ArrayList();
                }
                permitted_names[tag].add(name);
            }
        }
        // array of lists with excluded General Names divided by type
        excluded_names = new ArrayList[9];
        if (excludedSubtrees != null) {
            Iterator it =  excludedSubtrees.getSubtrees().iterator();
            while (it.hasNext()) {
                GeneralName name = ((GeneralSubtree) it.next()).getBase();
                //System.out.println("EXCLUDED: "+name);
                int tag = name.getTag();
                if (excluded_names[tag] == null) {
                    excluded_names[tag] = new ArrayList();
                }
                excluded_names[tag].add(name);
            }
        }