diff options
| author | Casey Marshall <csm@gnu.org> | 2004-11-07 19:40:56 +0000 |
|---|---|---|
| committer | Casey Marshall <csm@gnu.org> | 2004-11-07 19:40:56 +0000 |
| commit | d5e5ea8d8e78c6ae0f00d7fb17ac0bc2df29be69 (patch) | |
| tree | eac9a7f7f171c91de8d95b5d0f8b4fcae50d132a /gnu/java/security/x509/X500DistinguishedName.java | |
| parent | fca717776a5ad8252cd06a381cee650cbc8289b5 (diff) | |
| download | classpath-d5e5ea8d8e78c6ae0f00d7fb17ac0bc2df29be69.tar.gz | |
2004-11-07 Casey Marshall <csm@gnu.org>
* gnu/java/security/provider/Gnu.java
(<init>): add entries in a priviliged action.
Add new algorithms.
* gnu/java/security/provider/X509CertificateFactory.java
(engineGenerateCertificate): chain exceptions.
(engineGenerateCertificates): likewise.
(engineGenerateCRL): likewise.
(engineGenerateCRLs): likewise.
(engineGenerateCertPath): new methods.
(generateCert): throw exception if 'inStream' is null.
(generateCRL): likewise.
* gnu/java/security/x509/X500DistinguishedName.java: replaced with
version from GNU Crypto CVS.
* gnu/java/security/x509/X509CRL.java: likewise.
* gnu/java/security/x509/X509CRLEntry.java: likewise.
* gnu/java/security/x509/X509Certificate.java: likewise.
* java/security/cert/TrustAnchor.java: call 'toString' and not
toRFC2253.
* gnu/java/security/provider/CollectionCertStoreImpl.java,
* gnu/java/security/provider/EncodedKeyFactory.java,
* gnu/java/security/provider/GnuDHPublicKey.java,
* gnu/java/security/provider/GnuRSAPrivateKey.java,
* gnu/java/security/provider/GnuRSAPublicKey.java,
* gnu/java/security/provider/MD2withRSA.java,
* gnu/java/security/provider/MD4withRSA.java,
* gnu/java/security/provider/MD5withRSA.java,
* gnu/java/security/provider/PKIXCertPathValidatorImpl.java,
* gnu/java/security/provider/RSA.java,
* gnu/java/security/provider/RSAKeyFactory.java,
* gnu/java/security/provider/SHA1withRSA.java,
* gnu/java/security/x509/GnuPKIExtension.java,
* gnu/java/security/x509/PolicyNodeImpl.java,
* gnu/java/security/x509/Util.java,
* gnu/java/security/x509/X509CRLSelectorImpl.java,
* gnu/java/security/x509/X509CertPath.java,
* gnu/java/security/x509/X509CertSelectorImpl.java,
* gnu/java/security/x509/ext/AuthorityKeyIdentifier.java,
* gnu/java/security/x509/ext/BasicConstraints.java,
* gnu/java/security/x509/ext/CRLNumber.java,
* gnu/java/security/x509/ext/CertificatePolicies.java,
* gnu/java/security/x509/ext/ExtendedKeyUsage.java,
* gnu/java/security/x509/ext/Extension.java,
* gnu/java/security/x509/ext/GeneralNames.java,
* gnu/java/security/x509/ext/IssuerAlternativeNames.java,
* gnu/java/security/x509/ext/KeyUsage.java,
* gnu/java/security/x509/ext/PolicyConstraint.java,
* gnu/java/security/x509/ext/PolicyMappings.java,
* gnu/java/security/x509/ext/PrivateKeyUsagePeriod.java,
* gnu/java/security/x509/ext/ReasonCode.java,
* gnu/java/security/x509/ext/SubjectAlternativeNames.java,
* gnu/java/security/x509/ext/SubjectKeyIdentifier.java:
new files.
Diffstat (limited to 'gnu/java/security/x509/X500DistinguishedName.java')
| -rw-r--r-- | gnu/java/security/x509/X500DistinguishedName.java | 1036 |
1 files changed, 383 insertions, 653 deletions
diff --git a/gnu/java/security/x509/X500DistinguishedName.java b/gnu/java/security/x509/X500DistinguishedName.java index 8a715677b..64e320bef 100644 --- a/gnu/java/security/x509/X500DistinguishedName.java +++ b/gnu/java/security/x509/X500DistinguishedName.java @@ -1,5 +1,5 @@ -/* X500DistinguishedName.java -- X.500 name. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* X500DistinguishedName.java -- X.500 distinguished name. + Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -38,121 +38,35 @@ exception statement from your version. */ package gnu.java.security.x509; -import gnu.java.io.ASN1ParsingException; -import gnu.java.security.OID; -import gnu.java.security.der.DER; -import gnu.java.security.der.DERReader; -import gnu.java.security.der.DERValue; -import gnu.java.security.der.DERWriter; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; +import java.io.EOFException; import java.io.InputStream; import java.io.IOException; -import java.io.StreamTokenizer; +import java.io.Reader; import java.io.StringReader; + +import java.security.Principal; + +import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; -/** - * A X.500 distinguished name. Distinguished names are sequences of - * ATTRIB=VALUE pairs, where ATTRIB is one of the following: - * - * <table cellpadding="0" cellspacing="0" border="0"> - * <tr> - * <th bgcolor="#CCCCFF" align="left">Name</th> - * <th bgcolor="#CCCCFF" align="left">X.500 AttributeType</th> - * <th bgcolor="#CCCCFF" align="left">ObjectIdentifier</th> - * </tr> - * <tr> - * <td align="left">CN</td> - * <td align="left">commonName</td> - * <td align="left">2.5.4.3</td> - * </tr> - * <tr> - * <td align="left">C</td> - * <td align="left">countryName</td> - * <td align="left">2.5.4.6</td> - * </tr> - * <tr> - * <td align="left">L</td> - * <td align="left">localityName</td> - * <td align="left">2.5.4.7</td> - * </tr> - * <tr> - * <td align="left">ST</td> - * <td align="left">stateOrProvinceName</td> - * <td align="left">2.5.4.8</td> - * </tr> - * <tr> - * <td align="left">STREET</td> - * <td align="left">streetAddress</td> - * <td align="left">2.5.4.9</td> - * </tr> - * <tr> - * <td align="left">O</td> - * <td align="left">organizationName</td> - * <td align="left">2.5.4.10</td> - * </tr> - * <tr> - * <td align="left">OU</td> - * <td align="left">organizationUnitName</td> - * <td align="left">2.5.4.11</td> - * </tr> - * <tr> - * <td align="left">DC</td> - * <td align="left">domainComponent</td> - * <td align="left">0.9.2342.19200300.100.1.25</td> - * </tr> - * <tr> - * <td align="left">UID</td> - * <td align="left">userid</td> - * <td align="left"0.9.2342.19200300.100.1.1></td> - * </tr> - * <tr> - * <td align="left">DNQ or DNQUALIFIER(*)</td> - * <td align="left">domainNameQualifier</td> - * <td align="left">2.5.4.46</td> - * </tr> - * <tr> - * <td align="left">SURNAME(*)</td> - * <td align="left">name</td> - * <td align="left">2.5.4.41</td> - * </tr> - * <tr> - * <td align="left">GIVENNAME(*)</td> - * <td align="left">givenName</td> - * <td align="left">2.5.4.42</td> - * </tr> - * <tr> - * <td align="left">INITIALS(*)</td> - * <td align="left">initials</td> - * <td align="left">2.5.4.43</td> - * </tr> - * <tr> - * <td align="left">EMAILADDRESS(*)</td> - * <td align="left">emailAddress</td> - * <td align="left">2.5.4.44</td> - * </tr> - * </table> - * - * <p><i>(*) = attributes not specified in RFC1779 or RFC2253, but - * recognized anyway.</i> - * - * <p>Distinguished names of this form are used in the lightweight - * directory access protocol (LDAP) and in the issuer and subject fields - * of X.509 certificates. - * - * @author Casey Marshall (rsdio@metastatic.org) - * @see javax.security.auth.x500.X500Principal - * @status DER decoding/encoding works, RFC1779 and RFC2253 need to be - * made more robust. - */ -public class X500DistinguishedName +import gnu.java.security.der.DER; +import gnu.java.security.der.DERReader; +import gnu.java.security.der.DERValue; +import gnu.java.security.OID; + +public class X500DistinguishedName implements Principal { // Constants and fields. - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------- public static final OID CN = new OID("2.5.4.3"); public static final OID C = new OID("2.5.4.6"); @@ -171,651 +85,467 @@ public class X500DistinguishedName public static final OID DC = new OID("0.9.2342.19200300.100.1.25"); public static final OID UID = new OID("0.9.2342.19200300.100.1.1"); - private String commonName; - private String country; - private String locality; - private String orgUnit; - private String organization; - private String street; - private String state; - private String title; - private String dnQualifier; - private String surname; - private String givenName; - private String initials; - private String generation; - private String email; - private String domainComponent; - private String userid; - - private String nameRFC1779; - private String nameRFC2253; - private String nameCanonical; - - private transient byte[] encoded; + private List components; + private Map currentRdn; + private boolean fixed; + private String stringRep; + private byte[] encoded; // Constructors. - // ------------------------------------------------------------------------ - - /** - * Create a new X500DistinguishedName from the RFC1779 or RFC2253 - * encoded form. - * - * @param name The encoded name. - * @throws IllegalArgumentException If the name cannot be parsed. - */ + // ------------------------------------------------------------------------- + + public X500DistinguishedName() + { + components = new LinkedList(); + currentRdn = new LinkedHashMap(); + components.add(currentRdn); + } + public X500DistinguishedName(String name) { - if (name == null) - throw new NullPointerException(); + this(); try { - parseDN(name, true); + parseString(name); } - catch (Exception e) + catch (IOException ioe) { - parseDN(name, false); + throw new IllegalArgumentException(ioe.toString()); } } - /** - * Create a new X500DistinguishedName from the DER encoded bytes. - * - * @param encoded The encoded form. - * @throws IOException If the bytes are not a valid DER construct. - */ public X500DistinguishedName(byte[] encoded) throws IOException { - this(new ByteArrayInputStream(encoded)); + this(); + parseDer(new DERReader(encoded)); } - /** - * Create a new X500DistinguishedName from the DER encoded bytes. - * - * @param encoded The encoded form. - * @throws IOException If the bytes are not a valid DER construct. - */ public X500DistinguishedName(InputStream encoded) throws IOException { - parseDER(encoded); + this(); + parseDer(new DERReader(encoded)); } // Instance methods. - // ------------------------------------------------------------------------ - - public boolean equals(Object o) - { - return - (commonName != null && - commonName.equals(((X500DistinguishedName) o).commonName)) && - (country != null && - country.equals(((X500DistinguishedName) o).country)) && - (locality != null && - locality.equals(((X500DistinguishedName) o).locality)) && - (orgUnit != null && - orgUnit.equals(((X500DistinguishedName) o).orgUnit)) && - (organization != null && - organization.equals(((X500DistinguishedName) o).organization)) && - (street != null && - street.equals(((X500DistinguishedName) o).street)) && - (state != null && - state.equals(((X500DistinguishedName) o).state)) && - (domainComponent != null && - domainComponent.equals(((X500DistinguishedName) o).domainComponent)) && - (title != null && - title.equals(((X500DistinguishedName) o).title)) && - (dnQualifier != null && - dnQualifier.equals(((X500DistinguishedName) o).dnQualifier)) && - (surname != null && - surname.equals(((X500DistinguishedName) o).surname)) && - (givenName != null && - givenName.equals(((X500DistinguishedName) o).givenName)) && - (initials != null && - initials.equals(((X500DistinguishedName) o).initials)) && - (generation != null && - generation.equals(((X500DistinguishedName) o).generation)) && - (email != null && - email.equals(((X500DistinguishedName) o).email)) && - (userid != null && - userid.equals(((X500DistinguishedName) o).userid)); - } - - public byte[] getEncoded() - { - if (encoded == null) - encoded = encodeDER(); - return (byte[]) encoded.clone(); - } - - private static String quote(String str) - { - if (str.indexOf(" ") > 0 || str.indexOf("\f") > 0 || - str.indexOf("\n") > 0 || str.indexOf("\r") > 0 || - str.indexOf("\t") > 0) - str = '"' + str + '"'; - // XXX needs regex - //return str.replaceAll("([,+\"\\<>;])", "\\\1"); - return str; - } - - public String toRFC1779() - { - if (nameRFC1779 != null) - return nameRFC1779; - StringBuffer buf = new StringBuffer(); - if (commonName != null) - buf.append("CN=").append(quote(commonName)).append(", "); - if (country != null) - buf.append("C=").append(quote(country)).append(", "); - if (locality != null) - buf.append("L=").append(quote(locality)).append(", "); - if (orgUnit != null) - buf.append("OU=").append(quote(orgUnit)).append(", "); - if (organization != null) - buf.append("O=").append(quote(organization)).append(", "); - if (street != null) - buf.append("STREET=").append(quote(street)).append(", "); - if (state != null) - buf.append("ST=").append(quote(state)).append(", "); - if (title != null) - buf.append(T).append("=").append(quote(title)).append(", "); - if (dnQualifier != null) - buf.append(DNQ).append("=").append(quote(dnQualifier)).append(", "); - if (surname != null) - buf.append(NAME).append("=").append(quote(surname)).append(", "); - if (givenName != null) - buf.append(GIVENNAME).append("=").append(quote(givenName)).append(", "); - if (initials != null) - buf.append(INITIALS).append("=").append(quote(initials)).append(", "); - if (generation != null) - buf.append(GENERATION).append("=").append(quote(generation)).append(", "); - if (email != null) - buf.append(EMAIL).append("=").append(quote(email)).append(", "); - if (domainComponent != null) - buf.append(DC).append("=").append(quote(domainComponent)).append(", "); - if (userid != null) - buf.append(UID).append("=").append(quote(userid)).append(", "); - // XXX escapes - return (nameRFC1779 = buf.substring(0, buf.length()-2)); - } - - public String toRFC2253() - { - if (nameRFC2253 != null) - return nameRFC2253; - StringBuffer buf = new StringBuffer(); - if (commonName != null) - buf.append("CN=").append(quote(commonName)).append(","); - if (country != null) - buf.append("C=").append(quote(country)).append(","); - if (locality != null) - buf.append("L=").append(quote(locality)).append(","); - if (orgUnit != null) - buf.append("OU=").append(quote(orgUnit)).append(","); - if (organization != null) - buf.append("O=").append(quote(organization)).append(","); - if (street != null) - buf.append("STREET=").append(quote(street)).append(","); - if (state != null) - buf.append("ST=").append(quote(state)).append(","); - if (title != null) - buf.append(T).append("=").append(quote(title)).append(","); - if (dnQualifier != null) - buf.append(DNQ).append("=").append(quote(dnQualifier)).append(","); - if (surname != null) - buf.append(NAME).append("=").append(quote(surname)).append(","); - if (givenName != null) - buf.append(GIVENNAME).append("=").append(quote(givenName)).append(","); - if (initials != null) - buf.append(INITIALS).append("=").append(quote(initials)).append(","); - if (generation != null) - buf.append(GENERATION).append("=").append(quote(generation)).append(","); - if (email != null) - buf.append(EMAIL).append("=").append(quote(email)).append(","); - if (domainComponent != null) - buf.append(DC).append("=").append(quote(domainComponent)).append(","); - if (userid != null) - buf.append(UID).append("=").append(quote(userid)).append(","); - // XXX escapes. - return (nameRFC2253 = buf.substring(0, buf.length()-1)); - } + // ------------------------------------------------------------------------- - public String toCanonical() + public String getName() { - if (nameCanonical != null) - return nameCanonical; - nameCanonical = toRFC2253(); - return nameCanonical; // XXX canonicalize + return toString(); } - public String getCommonName() + public void newRelativeDistinguishedName() { - return commonName; + if (fixed || currentRdn.isEmpty()) return; + currentRdn = new LinkedHashMap(); + components.add(currentRdn); } - public String getCountry() + public int size() { - return country; + return components.size(); } - public String getLocality() + public int countComponents() { - return locality; + int count = 0; + for (Iterator it = components.iterator(); it.hasNext(); ) + { + count += ((Map) it.next()).size(); + } + return count; } - public String getOrganizationalUnit() + public boolean containsComponent(OID oid, String value) { - return orgUnit; + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map rdn = (Map) it.next(); + String s = (String) rdn.get(oid); + if (s == null) + continue; + if (compressWS(value).equalsIgnoreCase(compressWS(s))) + return true; + } + return false; } - public String getOrganization() + public String getComponent(OID oid) { - return organization; + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map rdn = (Map) it.next(); + if (rdn.containsKey(oid)) + return (String) rdn.get(oid); + } + return null; } - public String getStreet() + public String getComponent(OID oid, int rdn) { - return street; + if (rdn >= size()) + return null; + return (String) ((Map) components.get(rdn)).get(oid); } - public String getState() + public void putComponent(OID oid, String value) { - return state; + currentRdn.put(oid, value); } - public String getTitle() + public void putComponent(String name, String value) { - return title; + name = name.trim().toLowerCase(); + if (name.equals("cn")) + putComponent(CN, value); + else if (name.equals("c")) + putComponent(C, value); + else if (name.equals("l")) + putComponent(L, value); + else if (name.equals("street")) + putComponent(STREET, value); + else if (name.equals("st")) + putComponent(ST, value); + else if (name.equals("t")) + putComponent(T, value); + else if (name.equals("dnq")) + putComponent(DNQ, value); + else if (name.equals("name")) + putComponent(NAME, value); + else if (name.equals("givenname")) + putComponent(GIVENNAME, value); + else if (name.equals("initials")) + putComponent(INITIALS, value); + else if (name.equals("generation")) + putComponent(GENERATION, value); + else if (name.equals("email")) + putComponent(EMAIL, value); + else if (name.equals("dc")) + putComponent(DC, value); + else if (name.equals("uid")) + putComponent(UID, value); + else + putComponent(new OID(name), value); } - public String getDNQualifier() + public void setUnmodifiable() { - return dnQualifier; + if (fixed) return; + fixed = true; + List newComps = new ArrayList(components.size()); + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map rdn = (Map) it.next(); + rdn = Collections.unmodifiableMap(rdn); + newComps.add(rdn); + } + components = Collections.unmodifiableList(newComps); + currentRdn = Collections.EMPTY_MAP; } - public String getSurname() + public int hashCode() { - return surname; + int sum = 0; + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map m = (Map) it.next(); + for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); ) + { + Map.Entry e = (Map.Entry) it2.next(); + sum += e.getKey().hashCode(); + sum += e.getValue().hashCode(); + } + } + return sum; } - public String getGivenName() + public boolean equals(Object o) { - return givenName; + if (!(o instanceof X500DistinguishedName)) + return false; + if (size() != ((X500DistinguishedName) o).size()) + return false; + for (int i = 0; i < size(); i++) + { + Map m = (Map) components.get(i); + for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); ) + { + Map.Entry e = (Map.Entry) it2.next(); + OID oid = (OID) e.getKey(); + String v1 = (String) e.getValue(); + String v2 = ((X500DistinguishedName) o).getComponent(oid, i); + if (!compressWS(v1).equalsIgnoreCase(compressWS(v2))) + return false; + } + } + return true; } - public String getInitials() + public String toString() { - return initials; + if (fixed && stringRep != null) + return stringRep; + StringBuffer str = new StringBuffer(); + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map m = (Map) it.next(); + for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); ) + { + Map.Entry entry = (Map.Entry) it2.next(); + OID oid = (OID) entry.getKey(); + String value = (String) entry.getValue(); + if (oid.equals(CN)) + str.append("CN"); + else if (oid.equals(C)) + str.append("C"); + else if (oid.equals(L)) + str.append("L"); + else if (oid.equals(ST)) + str.append("ST"); + else if (oid.equals(STREET)) + str.append("STREET"); + else if (oid.equals(O)) + str.append("O"); + else if (oid.equals(OU)) + str.append("OU"); + else if (oid.equals(T)) + str.append("T"); + else if (oid.equals(DNQ)) + str.append("DNQ"); + else if (oid.equals(NAME)) + str.append("NAME"); + else + str.append(oid.toString()); + str.append('='); + str.append(value); + if (it2.hasNext()) + str.append("+"); + } + if (it.hasNext()) + str.append(','); + } + return (stringRep = str.toString()); } - public String getGeneration() + public byte[] getDer() { - return generation; + if (fixed && encoded != null) + return (byte[]) encoded.clone(); + ArrayList name = new ArrayList(components.size()); + for (Iterator it = components.iterator(); it.hasNext(); ) + { + Map m = (Map) it.next(); + if (m.isEmpty()) + continue; + Set rdn = new HashSet(); + for (Iterator it2 = m.entrySet().iterator(); it2.hasNext(); ) + { + Map.Entry e = (Map.Entry) it.next(); + ArrayList atav = new ArrayList(2); + atav.add(new DERValue(DER.OBJECT_IDENTIFIER, e.getKey())); + atav.add(new DERValue(DER.UTF8_STRING, e.getValue())); + rdn.add(new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, atav)); + } + name.add(new DERValue(DER.SET|DER.CONSTRUCTED, rdn)); + } + DERValue val = new DERValue(DER.SEQUENCE|DER.CONSTRUCTED, name); + return (byte[]) (encoded = val.getEncoded()).clone(); } - public String getEmail() - { - return email; - } + // Own methods. + // ------------------------------------------------------------------------- - public String getDomain() - { - return domainComponent; - } + private int sep; - public String getUserID() + private void parseString(String str) throws IOException { - return userid; + Reader in = new StringReader(str); + while (true) + { + String key = readAttributeType(in); + if (key == null) + break; + String value = readAttributeValue(in); + putComponent(key, value); + if (sep == ',') + newRelativeDistinguishedName(); + } + setUnmodifiable(); } - // Own methods. - // ------------------------------------------------------------------------ - - private static String unquote(String str) + private String readAttributeType(Reader in) throws IOException { - if (str.startsWith("\"") && str.endsWith("\"")) - str = str.substring(1, str.length()-1); - // XXX needs regex - //return str.replaceAll("\\([,+\"\\<>;])", "\1"); - return str; + StringBuffer buf = new StringBuffer(); + int ch; + while ((ch = in.read()) != '=') + { + if (ch == -1) + { + if (buf.length() > 0) + throw new EOFException(); + return null; + } + if (ch > 127) + throw new IOException("Invalid char: " + (char) ch); + if (Character.isLetterOrDigit((char) ch) || ch == '-' || ch == '.') + buf.append((char) ch); + else + throw new IOException("Invalid char: " + (char) ch); + } + return buf.toString(); } - private void parseDN(String name, boolean rfc2253) + private String readAttributeValue(Reader in) throws IOException { - if (name.length() == 0) - throw new IllegalArgumentException("zero-length distinguished name"); - StreamTokenizer parse = new StreamTokenizer(new StringReader(name)); - parse.resetSyntax(); - parse.wordChars('\000', '~'); - parse.ordinaryChar('#'); - parse.ordinaryChar(','); - parse.ordinaryChar('='); - parse.ordinaryChar('<'); - parse.ordinaryChar('>'); - parse.ordinaryChar(';'); - parse.ordinaryChar('\\'); - parse.quoteChar('"'); - String attrib = null; - String value = null; - int token, lastToken = ','; - while (true) + StringBuffer buf = new StringBuffer(); + int ch = in.read(); + if (ch == '#') { - try + while (true) { - token = parse.nextToken(); + ch = in.read(); + if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') + || Character.isDigit((char) ch)) + buf.append((char) ch); + else if (ch == '+' || ch == ',') + { + sep = ch; + String hex = buf.toString(); + return new String(Util.toByteArray(hex)); + } + else + throw new IOException("illegal character: " + (char) ch); } - catch (IOException ioe) + } + else if (ch == '"') + { + while (true) { - throw new IllegalArgumentException(); + ch = in.read(); + if (ch == '"') + break; + else if (ch == '\\') + { + ch = in.read(); + if (ch == -1) + throw new EOFException(); + if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') + || Character.isDigit((char) ch)) + { + int i = Character.digit((char) ch, 16) << 4; + ch = in.read(); + if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') + || Character.isDigit((char) ch))) + throw new IOException("illegal hex char"); + i |= Character.digit((char) ch, 16); + buf.append((char) i); + } + else + buf.append((char) ch); + } + else + buf.append((char) ch); } - switch (token) + sep = in.read(); + if (sep != '+' || sep != ',') + throw new IOException("illegal character: " + (char) ch); + return buf.toString(); + } + else + { + while (true) { - case StreamTokenizer.TT_WORD: - if (lastToken == ',' || lastToken == '+' || - (!rfc2253 && lastToken == ';')) - attrib = parse.sval.trim(); - else if (lastToken == '=') - value = unquote(parse.sval.trim()); - else - throw new IllegalArgumentException(); - break; - case '"': - if (lastToken == '=') - value = parse.sval; - else - throw new IllegalArgumentException(); - break; - case ';': - if (rfc2253) - throw new IllegalArgumentException(); - case ',': - case '+': - if (attrib == null || value == null) - throw new IllegalArgumentException("extraneous separator"); - try - { - setAttribute(new OID(attrib), value); - } - catch (Exception x) - { - setAttribute(attrib, value); - } - attrib = null; - value = null; - break; - case '=': - break; - case StreamTokenizer.TT_EOF: - return; - default: - throw new IllegalArgumentException("unknown token " + (char)token - + " (" + token + ")"); + switch (ch) + { + case '+': + case ',': + sep = ch; + return buf.toString(); + case '\\': + ch = in.read(); + if (ch == -1) + throw new EOFException(); + if (('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') + || Character.isDigit((char) ch)) + { + int i = Character.digit((char) ch, 16) << 4; + ch = in.read(); + if (!(('a' <= ch && ch <= 'f') || ('A' <= ch && ch <= 'F') + || Character.isDigit((char) ch))) + throw new IOException("illegal hex char"); + i |= Character.digit((char) ch, 16); + buf.append((char) i); + } + else + buf.append((char) ch); + break; + case '=': + case '<': + case '>': + case '#': + case ';': + throw new IOException("illegal character: " + (char) ch); + case -1: + throw new EOFException(); + default: + buf.append((char) ch); + } } - lastToken = token; } } - private void parseDER(InputStream in) throws IOException + private void parseDer(DERReader der) throws IOException { - DERReader der = new DERReader(in); DERValue name = der.read(); if (!name.isConstructed()) - throw new ASN1ParsingException("badly formed Name"); + throw new IOException("malformed Name"); + encoded = name.getEncoded(); int len = 0; while (len < name.getLength()) { DERValue rdn = der.read(); - if (rdn.getValue() != DER.CONSTRUCTED_VALUE) - throw new ASN1ParsingException("badly formed RDNSequence"); + if (!rdn.isConstructed()) + throw new IOException("badly formed RDNSequence"); int len2 = 0; while (len2 < rdn.getLength()) { DERValue atav = der.read(); - if (atav.getValue() != DER.CONSTRUCTED_VALUE) - throw new ASN1ParsingException( - "badly formed AttributeTypeAndValue"); - OID atype = (OID) der.read().getValue(); - String aval = (String) der.read().getValue(); - setAttribute(atype, aval); - len2 += 1 + atav.getLength() - + DERWriter.definiteEncodingSize(atav.getLength()); + if (!atav.isConstructed()) + throw new IOException("badly formed AttributeTypeAndValue"); + DERValue val = der.read(); + if (val.getTag() != DER.OBJECT_IDENTIFIER) + throw new IOException("badly formed AttributeTypeAndValue"); + OID oid = (OID) val.getValue(); + val = der.read(); + if (!(val.getValue() instanceof String)) + throw new IOException("badly formed AttributeTypeAndValue"); + String value = (String) val.getValue(); + putComponent(oid, value); + len2 += atav.getEncodedLength(); } - len += len2 + 1 + DERWriter.definiteEncodingSize(name.getLength()); + len += rdn.getEncodedLength(); + if (len < name.getLength()) + newRelativeDistinguishedName(); } + setUnmodifiable(); } - private byte[] encodeDER() + private static String compressWS(String str) { - try + StringBuffer buf = new StringBuffer(); + char lastChar = 0; + for (int i = 0; i < str.length(); i++) { - LinkedList name = new LinkedList(); - if (commonName != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, CN)); - atav.add(new DERValue(DER.PRINTABLE_STRING, commonName)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (country != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, C)); - atav.add(new DERValue(DER.PRINTABLE_STRING, country)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (locality != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, L)); - atav.add(new DERValue(DER.PRINTABLE_STRING, locality)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (orgUnit != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, OU)); - atav.add(new DERValue(DER.PRINTABLE_STRING, orgUnit)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (organization != null) + char c = str.charAt(i); + if (Character.isWhitespace(c)) { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, O)); - atav.add(new DERValue(DER.PRINTABLE_STRING, organization)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); + if (!Character.isWhitespace(lastChar)) + buf.append(' '); } - if (street != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, STREET)); - atav.add(new DERValue(DER.PRINTABLE_STRING, street)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (state != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, ST)); - atav.add(new DERValue(DER.PRINTABLE_STRING, state)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (title != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, T)); - atav.add(new DERValue(DER.PRINTABLE_STRING, title)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (dnQualifier != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, DNQ)); - atav.add(new DERValue(DER.PRINTABLE_STRING, dnQualifier)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (surname != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, NAME)); - atav.add(new DERValue(DER.PRINTABLE_STRING, surname)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (givenName != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, GIVENNAME)); - atav.add(new DERValue(DER.PRINTABLE_STRING, givenName)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (initials != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, INITIALS)); - atav.add(new DERValue(DER.PRINTABLE_STRING, initials)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (generation != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, GENERATION)); - atav.add(new DERValue(DER.PRINTABLE_STRING, generation)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (email != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, EMAIL)); - atav.add(new DERValue(DER.PRINTABLE_STRING, email)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (domainComponent != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, DC)); - atav.add(new DERValue(DER.PRINTABLE_STRING, domainComponent)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - if (userid != null) - { - HashSet rdn = new HashSet(); - LinkedList atav = new LinkedList(); - atav.add(new DERValue(DER.OBJECT_IDENTIFIER, UID)); - atav.add(new DERValue(DER.PRINTABLE_STRING, userid)); - rdn.add(new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, atav)); - name.add(new DERValue(DER.CONSTRUCTED | DER.SET, rdn)); - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - DERWriter.write(out, new DERValue(DER.CONSTRUCTED|DER.SEQUENCE, name)); - return out.toByteArray(); - } - catch (IOException ioe) - { - throw new Error(ioe); + else + buf.append(c); + lastChar = c; } - } - - private void setAttribute(String atype, String aval) - { - if (atype.equals("CN")) - commonName = aval; - else if (atype.equals("C")) - country = aval; - else if (atype.equals("L")) - locality = aval; - else if (atype.equals("ST")) - state = aval; - else if (atype.equals("STREET")) - street = aval; - else if (atype.equals("O")) - organization = aval; - else if (atype.equals("OU")) - orgUnit = aval; - else if (atype.equals("T")) - title = aval; - else if (atype.equals("DNQ") || atype.equals("DNQUALIFIER")) - dnQualifier = aval; - else if (atype.equals("SURNAME")) - surname = aval; - else if (atype.equals("GIVENNAME")) - givenName = aval; - else if (atype.equals("INITIALS")) - initials = aval; - else if (atype.equals("GENERATION")) - generation = aval; - else if (atype.equals("EMAILADDRESS")) - email = aval; - else if (atype.equals("DC")) - domainComponent = aval; - else if (atype.equals("UID")) - userid = aval; - else - throw new IllegalArgumentException("unknown attribute " + atype); - } - - private void setAttribute(OID atype, String aval) - { - if (atype.equals(CN)) - commonName = aval; - else if (atype.equals(C)) - country = aval; - else if (atype.equals(L)) - locality = aval; - else if (atype.equals(ST)) - state = aval; - else if (atype.equals(STREET)) - street = aval; - else if (atype.equals(O)) - organization = aval; - else if (atype.equals(OU)) - orgUnit = aval; - else if (atype.equals(T)) - title = aval; - else if (atype.equals(DNQ)) - dnQualifier = aval; - else if (atype.equals(NAME)) - surname = aval; - else if (atype.equals(GIVENNAME)) - givenName = aval; - else if (atype.equals(INITIALS)) - initials = aval; - else if (atype.equals(GENERATION)) - generation = aval; - else if (atype.equals(EMAIL)) - email = aval; - else if (atype.equals(DC)) - domainComponent = aval; - else if (atype.equals(UID)) - userid = aval; - else - throw new IllegalArgumentException("unknown attribute " + atype); + return buf.toString().trim(); } } |
