summaryrefslogtreecommitdiff
path: root/gnu/java/security/x509/X500DistinguishedName.java
diff options
context:
space:
mode:
authorCasey Marshall <csm@gnu.org>2004-11-07 19:40:56 +0000
committerCasey Marshall <csm@gnu.org>2004-11-07 19:40:56 +0000
commitd5e5ea8d8e78c6ae0f00d7fb17ac0bc2df29be69 (patch)
treeeac9a7f7f171c91de8d95b5d0f8b4fcae50d132a /gnu/java/security/x509/X500DistinguishedName.java
parentfca717776a5ad8252cd06a381cee650cbc8289b5 (diff)
downloadclasspath-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.java1036
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();
}
}