Commit fd375c53 by Andreas Tobler

X500Principal.java: Replaced with GNU Crypto's version.

2004-09-21  Andreas Tobler  <a.tobler@schweiz.ch>

	* javax/security/auth/x500/X500Principal.java: Replaced with GNU
	Crypto's version.

From-SVN: r87796
parent 6f5ce93b
...@@ -38,16 +38,38 @@ exception statement from your version. */ ...@@ -38,16 +38,38 @@ exception statement from your version. */
package javax.security.auth.x500; package javax.security.auth.x500;
import gnu.java.security.x509.X500DistinguishedName; import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DEREncodingException;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.EOFException;
import java.io.NotActiveException; import java.io.NotActiveException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringReader;
import java.security.Principal; 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.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public final class X500Principal implements Principal, Serializable public final class X500Principal implements Principal, Serializable
{ {
private static final long serialVersionUID = -500463348111345721L; private static final long serialVersionUID = -500463348111345721L;
...@@ -56,44 +78,66 @@ public final class X500Principal implements Principal, Serializable ...@@ -56,44 +78,66 @@ public final class X500Principal implements Principal, Serializable
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
public static final String CANONICAL = "CANONICAL"; public static final String CANONICAL = "CANONICAL";
public static final String RFC1779 = "RFC1779"; public static final String RFC1779 = "RFC1779";
public static final String RFC2253 = "RFC2253"; public static final String RFC2253 = "RFC2253";
private transient X500DistinguishedName name; private static final OID CN = new OID("2.5.4.3");
private static final OID C = new OID("2.5.4.6");
private static final OID L = new OID("2.5.4.7");
private static final OID ST = new OID("2.5.4.8");
private static final OID STREET = new OID("2.5.4.9");
private static final OID O = new OID("2.5.4.10");
private static final OID OU = new OID("2.5.4.11");
private static final OID DC = new OID("0.9.2342.19200300.100.1.25");
private static final OID UID = new OID("0.9.2342.19200300.100.1.1");
private transient List components;
private transient Map currentRdn;
private transient boolean fixed;
private transient byte[] encoded;
// Constructors. // Constructors.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
public X500Principal(String name) private X500Principal()
{ {
if (name == null) components = new LinkedList();
throw new NullPointerException(); currentRdn = new LinkedHashMap();
this.name = new X500DistinguishedName(name); components.add (currentRdn);
} }
public X500Principal(byte[] encoded) public X500Principal (String name)
{ {
this();
if (name == null)
throw new NullPointerException();
try try
{ {
name = new X500DistinguishedName(encoded); parseString (name);
} }
catch (IOException ioe) catch (IOException ioe)
{ {
throw new IllegalArgumentException(ioe.toString()); IllegalArgumentException iae = new IllegalArgumentException("malformed name");
iae.initCause (ioe);
throw iae;
}
} }
public X500Principal (byte[] encoded)
{
this(new ByteArrayInputStream (encoded));
} }
public X500Principal(InputStream encoded) public X500Principal (InputStream encoded)
{ {
this();
try try
{ {
name = new X500DistinguishedName(encoded); parseDer (encoded);
} }
catch (IOException ioe) catch (IOException ioe)
{ {
throw new IllegalArgumentException(ioe.toString()); throw new IllegalArgumentException (ioe.toString());
} }
} }
...@@ -102,42 +146,389 @@ public final class X500Principal implements Principal, Serializable ...@@ -102,42 +146,389 @@ public final class X500Principal implements Principal, Serializable
public boolean equals(Object o) public boolean equals(Object o)
{ {
return ((X500Principal) o).name.equals(name); if (!(o instanceof X500Principal))
return false;
if (size() != ((X500Principal) 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 = ((X500Principal) o).getComponent (oid, i);
if (v2 == null)
return false;
if (!compressWS (v1).equalsIgnoreCase (compressWS (v2)))
return false;
}
}
return true;
} }
public byte[] getEncoded() public byte[] getEncoded()
{ {
return name.getEncoded(); if (encoded == null)
encodeDer();
return (byte[]) encoded.clone();
} }
public String getName() public String getName()
{ {
return getName(RFC2253); return getName (RFC2253);
}
public String getName (final String format)
{
boolean rfc2253 = RFC2253.equalsIgnoreCase (format) ||
CANONICAL.equalsIgnoreCase (format);
boolean rfc1779 = RFC1779.equalsIgnoreCase (format);
boolean canon = CANONICAL.equalsIgnoreCase (format);
if (! (rfc2253 || rfc1779 || canon))
throw new IllegalArgumentException ("unsupported format " + format);
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 (DC) && rfc2253)
str.append ("DC");
else if (oid.equals ("UID") && rfc2253)
str.append ("UID");
else
str.append (oid.toString());
str.append('=');
str.append(value);
if (it2.hasNext())
str.append('+');
}
if (it.hasNext())
str.append(',');
}
if (canon)
return str.toString().toUpperCase (Locale.US).toLowerCase (Locale.US);
return str.toString();
} }
public String getName(String format) public String toString()
{ {
if (format.equalsIgnoreCase(RFC2253)) return getName (RFC2253);
return name.toRFC2253();
else if (format.equalsIgnoreCase(RFC1779))
return name.toRFC1779();
else if (format.equalsIgnoreCase(CANONICAL))
return name.toCanonical();
throw new IllegalArgumentException("unsupported format " + format);
} }
// Serialization methods. // Serialization methods.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
private void writeObject(ObjectOutputStream out) throws IOException private void writeObject (ObjectOutputStream out) throws IOException
{ {
out.writeObject(name.getEncoded()); if (encoded != null)
encodeDer();
out.writeObject (encoded);
} }
private void readObject(ObjectInputStream in) private void readObject (ObjectInputStream in)
throws IOException, NotActiveException, ClassNotFoundException throws IOException, NotActiveException, ClassNotFoundException
{ {
byte[] buf = (byte[]) in.readObject(); byte[] buf = (byte[]) in.readObject();
name = new X500DistinguishedName(buf); parseDer (new ByteArrayInputStream (buf));
}
// Own methods.
// -------------------------------------------------------------------------
private int size()
{
return components.size();
}
private String getComponent(OID oid, int rdn)
{
if (rdn >= size())
return null;
return (String) ((Map) components.get (rdn)).get (oid);
}
private void encodeDer()
{
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);
encoded = val.getEncoded();
}
private int sep;
private void parseString(String str) throws IOException
{
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();
}
}
private String readAttributeType(Reader in) throws IOException
{
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 String readAttributeValue(Reader in) throws IOException
{
StringBuffer buf = new StringBuffer();
int ch = in.read();
if (ch == '#')
{
while (true)
{
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(toByteArray(hex));
}
else
throw new IOException("illegal character: " + (char) ch);
}
}
else if (ch == '"')
{
while (true)
{
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);
}
sep = in.read();
if (sep != '+' || sep != ',')
throw new IOException("illegal character: " + (char) ch);
return buf.toString();
}
else
{
while (true)
{
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);
}
}
}
}
private void parseDer (InputStream encoded) throws IOException
{
DERReader der = new DERReader (encoded);
DERValue name = der.read();
if (!name.isConstructed())
throw new IOException ("malformed Name");
this.encoded = name.getEncoded();
int len = 0;
while (len < name.getLength())
{
DERValue rdn = der.read();
if (!rdn.isConstructed())
throw new IOException ("badly formed RDNSequence");
int len2 = 0;
while (len2 < rdn.getLength())
{
DERValue atav = der.read();
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 += rdn.getEncodedLength();
if (len < name.getLength())
newRelativeDistinguishedName();
}
}
private void newRelativeDistinguishedName()
{
currentRdn = new LinkedHashMap();
components.add(currentRdn);
}
private void putComponent(OID oid, String value)
{
currentRdn.put(oid, value);
}
private void putComponent(String name, String value)
{
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("dc"))
putComponent(DC, value);
else if (name.equals("uid"))
putComponent(UID, value);
else
putComponent(new OID(name), value);
}
private static String compressWS(String str)
{
StringBuffer buf = new StringBuffer();
char lastChar = 0;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (Character.isWhitespace(c))
{
if (!Character.isWhitespace(lastChar))
buf.append(' ');
}
else
buf.append(c);
lastChar = c;
}
return buf.toString().trim();
}
private static byte[] toByteArray (String str)
{
int limit = str.length();
byte[] result = new byte[((limit + 1) / 2)];
int i = 0, j = 0;
if ((limit % 2) == 1)
{
result[j++] = (byte) Character.digit (str.charAt(i++), 16);
}
while (i < limit)
{
result[j ] = (byte) (Character.digit (str.charAt(i++), 16) << 4);
result[j++] |= (byte) Character.digit (str.charAt(i++), 16);
}
return result;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment