diff options
Diffstat (limited to 'pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java')
-rw-r--r-- | pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java | 824 |
1 files changed, 0 insertions, 824 deletions
diff --git a/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java b/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java deleted file mode 100644 index 1245cc6bd..000000000 --- a/pki/base/util/src/netscape/security/x509/LdapV3DNStrConverter.java +++ /dev/null @@ -1,824 +0,0 @@ -// --- BEGIN COPYRIGHT BLOCK --- -// This program 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; version 2 of the License. -// -// This program 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 General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -// -// (C) 2007 Red Hat, Inc. -// All rights reserved. -// --- END COPYRIGHT BLOCK --- -package netscape.security.x509; - -import java.io.ByteArrayOutputStream; -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.PushbackReader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.UnsupportedCharsetException; -import java.util.Arrays; -import java.util.Vector; - -import netscape.security.util.DerValue; -import netscape.security.util.ObjectIdentifier; - -/** - * A converter that converts Ldap v3 DN strings as specified in - * draft-ietf-asid-ldapv3-dn-03.txt to a X500Name, RDN or AVA and - * vice versa. - * - * @see LdapDNStrConverter - * @see X500Name - * @see RDN - * @see AVA - * @see X500NameAttrMap - * - * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. - */ - -public class LdapV3DNStrConverter extends LdapDNStrConverter { - // - // Constructors - // - - /** - * Constructs a LdapV3DNStrConverter using the global default - * X500NameAttrMap and accept OIDs not in the default X500NameAttrMap. - * - * @see X500NameAttrMap - */ - public LdapV3DNStrConverter() { - attrMap = X500NameAttrMap.getDefault(); - - acceptUnknownOids = true; - } - - /** - * Constructs a LdapV3DNStrConverter using the specified X500NameAttrMap - * and a boolean indicating whether to accept OIDs not listed in the - * X500NameAttrMap. - * - * @param attributeMap a X500NameAttrMap - * @param doAcceptUnknownOids whether to convert unregistered OIDs - * (oids not in the X500NameAttrMap) - * @see X500NameAttrMap - */ - public LdapV3DNStrConverter(X500NameAttrMap attributeMap, - boolean doAcceptUnknownOids) { - attrMap = attributeMap; - acceptUnknownOids = doAcceptUnknownOids; - - } - - // - // public parsing methods - // From LdapDNStrConverter interface - // - - /** - * Parse a Ldap v3 DN string to a X500Name. - * - * @param dn a LDAP v3 DN String - * @return a X500Name - * @exception IOException if an error occurs during the conversion. - */ - public X500Name parseDN(String dn) - throws IOException { - return parseDN(dn, null); - } - - /** - * Like parseDN(String) with a DER encoding order given as argument for - * Directory Strings. - */ - public X500Name parseDN(String dn, byte[] encodingOrder) - throws IOException { - StringReader dn_reader = new StringReader(dn); - PushbackReader in = new PushbackReader(dn_reader, 5); - - return parseDN(in, encodingOrder); - } - - /** - * Parse a Ldap v3 DN string with a RDN component to a RDN - * - * @param rdn a LDAP v3 DN String - * @return a RDN - * @exception IOException if an error occurs during the conversion. - */ - public RDN parseRDN(String rdn) - throws IOException { - return parseRDN(rdn, null); - } - - /** - * Like parseRDN(String) with a DER encoding order given as argument for - * Directory Strings. - */ - public RDN parseRDN(String rdn, byte[] encodingOrder) - throws IOException { - StringReader rdn_reader = new StringReader(rdn); - PushbackReader in = new PushbackReader(rdn_reader, 5); - - return parseRDN(in, null); - } - - /** - * Parse a Ldap v3 DN string with a AVA component to a AVA. - * - * @param ava a LDAP v3 DN string - * @return a AVA - */ - public AVA parseAVA(String ava) - throws IOException { - return parseAVA(ava, null); - } - - /** - * Like parseDN(String) with a DER encoding order given as argument for - * Directory Strings. - */ - public AVA parseAVA(String ava, byte[] encodingOrder) - throws IOException { - StringReader ava_reader = new StringReader(ava); - PushbackReader in = new PushbackReader(ava_reader, 5); - - return parseAVA(in, encodingOrder); - } - - // - // public parsing methods called by other methods. - // - - /** - * Parses a Ldap DN string in a string reader to a X500Name. - * - * @param in Pushback string reader for a Ldap DN string. - * The pushback reader must have a pushback buffer size > 2. - * - * @return a X500Name - * - * @exception IOException if any reading or parsing error occurs. - */ - public X500Name parseDN(PushbackReader in) - throws IOException { - return parseDN(in, null); - } - - /** - * Like parseDN(PushbackReader in) with a DER encoding order given as - * argument for Directory Strings. - */ - public X500Name parseDN(PushbackReader in, byte[] encodingOrder) - throws IOException { - RDN rdn; - int lastChar; - Vector<RDN> rdnVector = new Vector<RDN>(); - RDN names[]; - int i, j; - - do { - rdn = parseRDN(in, encodingOrder); - rdnVector.addElement(rdn); - lastChar = in.read(); - } while (lastChar == ',' || lastChar == ';'); - - names = new RDN[rdnVector.size()]; - for (i = 0, j = rdnVector.size() - 1; i < rdnVector.size(); i++, j--) - names[j] = (RDN) rdnVector.elementAt(i); - return new X500Name(names); - } - - /** - * Parses Ldap DN string with a rdn component - * from a string reader to a RDN. The string reader will point - * to the separator after the rdn component or -1 if at end of string. - * - * @param in Pushback string reader containing a Ldap DN string with - * at least one rdn component. - * The pushback reader must have a pushback buffer size > 2. - * - * @return RDN object of the first rdn component in the Ldap DN string. - * - * @exception IOException if any read or parse error occurs. - */ - public RDN parseRDN(PushbackReader in) - throws IOException { - return parseRDN(in, null); - } - - /** - * Like parseRDN(PushbackReader) with a DER encoding order given as - * argument for Directory Strings. - */ - public RDN parseRDN(PushbackReader in, byte[] encodingOrder) - throws IOException { - Vector<AVA> avaVector = new Vector<AVA>(); - AVA ava; - int lastChar; - AVA assertion[]; - - do { - ava = parseAVA(in, encodingOrder); - avaVector.addElement(ava); - lastChar = in.read(); - } while (lastChar == '+'); - - if (lastChar != -1) - in.unread(lastChar); - - assertion = new AVA[avaVector.size()]; - for (int i = 0; i < avaVector.size(); i++) - assertion[i] = (AVA) avaVector.elementAt(i); - return new RDN(assertion); - } - - /** - * Parses a Ldap DN string with a AVA component - * from a string reader to an AVA. The string reader will point - * to the AVA separator after the ava string or -1 if end of string. - * - * @param in a Pushback reader containg a Ldap string with - * at least one AVA component. - * The Pushback reader must have a pushback buffer size > 2. - * - * @return AVA object of the first AVA component in the Ldap DN string. - */ - public AVA parseAVA(PushbackReader in) - throws IOException { - return parseAVA(in, null); - } - - /** - * Like parseAVA(PushbackReader) with a DER encoding order given as - * argument for Directory Strings. - */ - public AVA parseAVA(PushbackReader in, byte[] encodingOrder) - throws IOException { - int c; - ObjectIdentifier oid; - DerValue value; - StringBuffer keywordBuf; - StringBuffer valueBuf; - ByteArrayOutputStream berStream; - char hexChar1, hexChar2; - CharArrayWriter hexCharsBuf; - String endChars; - - /* First get the keyword indicating the attribute's type, - * and map it to the appropriate OID. - */ - keywordBuf = new StringBuffer(); - for (;;) { - c = in.read(); - if (c == '=') - break; - if (c == -1) { - throw new IOException("Bad AVA format: Missing '='"); - } - keywordBuf.append((char) c); - } - oid = parseAVAKeyword(keywordBuf.toString()); - - /* Now parse the value. "#hex", a quoted string, or a string - * terminated by "+", ",", ";", ">". Whitespace before or after - * the value is stripped. - */ - for (c = in.read(); c == ' '; c = in.read()) - continue; - if (c == -1) - throw new IOException("Bad AVA format: Missing attribute value"); - - if (c == '#') { - /* - * NOTE per LDAPv3 dn string ietf standard the value represented - * by this form is a BER value. But we only support DER value here - * which is only a form of BER. - */ - berStream = new ByteArrayOutputStream(); - int b; - for (;;) { - hexChar1 = (char) (c = in.read()); - if (c == -1 || octoEndChars.indexOf(c) > 0) // end of value - break; - hexChar2 = (char) (c = in.read()); - if (hexDigits.indexOf(hexChar1) == -1 || - hexDigits.indexOf(hexChar2) == -1) - throw new IOException("Bad AVA value: bad hex value."); - b = (Character.digit(hexChar1, 16) << 4) + - Character.digit(hexChar2, 16); - berStream.write(b); - } - if (berStream.size() == 0) - throw new IOException("bad AVA format: invalid hex value"); - - value = parseAVAValue(berStream.toByteArray(), oid); - - while (c == ' ' && c != -1) - c = in.read(); - } else { - valueBuf = new StringBuffer(); - boolean quoted = false; - if (c == '"') { - quoted = true; - endChars = quotedEndChars; - if ((c = in.read()) == -1) - throw new IOException("Bad AVA format: Missing attrValue"); - } else { - endChars = valueEndChars; - } - - // QUOTATION * ( quotechar / pair ) QUOTATION - // quotechar = any character except '\' or QUOTATION - // pair = '\' ( special | '\' | QUOTATION | hexpair ) - while (c != -1 && endChars.indexOf(c) == -1) { - if (c == '\\') { - if ((c = in.read()) == -1) - throw new IOException("Bad AVA format: expecting " + - "escaped char."); - // expect escaping of special chars, space and CR. - if (specialChars.indexOf((char) c) != -1 || c == '\n' || - c == '\\' || c == '"' || c == ' ') { - valueBuf.append((char) c); - } else if (hexDigits.indexOf(c) != -1) { - hexCharsBuf = new CharArrayWriter(); - // handle sequence of '\' hexpair - do { - hexChar1 = (char) c; - hexChar2 = (char) (c = in.read()); - if (hexDigits.indexOf((char) c) == -1) - throw new IOException("Bad AVA format: " + - "invalid escaped hex pair"); - hexCharsBuf.write(hexChar1); - hexCharsBuf.write(hexChar2); - // read ahead to next '\' hex-char if any. - if ((c = in.read()) == -1) - break; - if (c != '\\') { - in.unread(c); - break; - } - if ((c = in.read()) == -1) - throw new IOException("Bad AVA format: " + - "expecting escaped char."); - if (hexDigits.indexOf((char) c) == -1) { - in.unread(c); - in.unread((int) '\\'); - break; - } - } while (true); - valueBuf.append( - getStringFromHexpairs(hexCharsBuf.toCharArray())); - } else { - throw new IOException("Bad AVA format: " + - "invalid escaping"); - } - } else - valueBuf.append((char) c); - c = in.read(); - } - - value = parseAVAValue( - valueBuf.toString().trim(), oid, encodingOrder); - - if (quoted) { // move to next non-white space - do { - c = in.read(); - } while (c == ' '); - if (c != -1 && valueEndChars.indexOf(c) == -1) - throw new IOException( - "Bad AVA format: separator expected at end of ava."); - } - } - - if (c != -1) - in.unread(c); - - return new AVA(oid, value); - } - - /** - * Converts a AVA keyword from a Ldap DN string to an ObjectIdentifier - * from the attribute map or, if this keyword is an OID not - * in the attribute map, create a new ObjectIdentifier for the keyword - * if acceptUnknownOids is true. - * - * @param avaKeyword AVA keyword from a Ldap DN string. - * - * @return a ObjectIdentifier object - * @exception IOException if the keyword is an OID not in the attribute - * map and acceptUnknownOids is false, or - * if an error occurs during conversion. - */ - public ObjectIdentifier parseAVAKeyword(String avaKeyword) - throws IOException { - String keyword = avaKeyword.toUpperCase().trim(); - String oid_str = null; - ObjectIdentifier oid, new_oid; - - if (Character.digit(keyword.charAt(0), 10) != -1) { - // value is an oid string of 1.2.3.4 - oid_str = keyword; - } else if (keyword.startsWith("oid.") || keyword.startsWith("OID.")) { - // value is an oid string of oid.1.2.3.4 or OID.1.2... - oid_str = keyword.substring(4); - } - - if (oid_str != null) { - // value is an oid string of 1.2.3.4 or oid.1.2.3.4 or OID.1.2... - new_oid = new ObjectIdentifier(oid_str); - oid = attrMap.getOid(new_oid); - if (oid == null) { - if (!acceptUnknownOids) - throw new IOException("Unknown AVA OID."); - oid = new_oid; - } - } else { - oid = attrMap.getOid(keyword); - if (oid == null) - throw new IOException("Unknown AVA keyword '" + keyword + "'."); - } - - return oid; - } - - /** - * Converts a AVA value from a Ldap dn string to a - * DerValue according the attribute type. For example, a value for - * CN, OU or O is expected to be a Directory String and will be converted - * to a DerValue of ASN.1 type PrintableString, T61String or - * UniversalString. A Directory String is a ASN.1 CHOICE of Printable, - * T.61 or Universal string. - * - * @param avaValueString a attribute value from a Ldap DN string. - * @param oid OID of the attribute. - * - * @return DerValue for the value. - * - * @exception IOException if an error occurs during conversion. - * @see AVAValueConverter - */ - public DerValue parseAVAValue(String avaValueString, ObjectIdentifier oid) - throws IOException { - return parseAVAValue(avaValueString, oid, null); - } - - /** - * Like parseAVAValue(String) with a DER encoding order given as argument - * for Directory Strings. - */ - public DerValue parseAVAValue( - String avaValueString, ObjectIdentifier oid, byte[] encodingOrder) - throws IOException { - AVAValueConverter valueConverter = attrMap.getValueConverter(oid); - if (valueConverter == null) { - if (!acceptUnknownOids) { - throw new IllegalArgumentException( - "Unrecognized OID for AVA value conversion"); - } else { - valueConverter = new GenericValueConverter(); - } - } - return valueConverter.getValue(avaValueString, encodingOrder); - } - - /** - * Converts a value in BER encoding, for example given in octothorpe form - * in a Ldap v3 dn string, to a DerValue. Checks if the BER encoded value - * is a legal value for the attribute. - * <p> - * <strong><i>NOTE:</i></strong> only DER encoded values are supported for the BER encoded value. - * - * @param berValue a value in BER encoding - * @param oid ObjectIdentifier of the attribute. - * - * @return DerValue for the BER encoded value - * @exception IOException if an error occurs during conversion. - */ - public DerValue parseAVAValue(byte[] berValue, ObjectIdentifier oid) - throws IOException { - AVAValueConverter valueConverter = attrMap.getValueConverter(oid); - if (valueConverter == null && !acceptUnknownOids) { - throw new IllegalArgumentException( - "Unrecognized OID for AVA value conversion"); - } else { - valueConverter = new GenericValueConverter(); - } - return valueConverter.getValue(berValue); - } - - // - // public encoding methods. - // - - /** - * Converts a X500Name object to a Ldap v3 DN string (except in unicode). - * - * @param x500name a X500Name - * - * @return a Ldap v3 DN String (except in unicode). - * - * @exception IOException if an error is encountered during conversion. - */ - public String encodeDN(X500Name x500name) - throws IOException { - RDN[] rdns = x500name.getNames(); - // String fullname = null; - StringBuffer fullname = new StringBuffer(); - String s; - int i; - if (rdns.length == 0) - return ""; - i = rdns.length - 1; - fullname.append(encodeRDN(rdns[i--])); - while (i >= 0) { - s = encodeRDN(rdns[i--]); - fullname.append(","); - fullname.append(s); - } - ; - return fullname.toString(); - } - - /** - * Converts a RDN to a Ldap v3 DN string (except in unicode). - * - * @param rdn a RDN - * - * @return a LDAP v3 DN string (except in unicode). - * - * @exception IOException if an error is encountered during conversion. - */ - public String encodeRDN(RDN rdn) - throws IOException { - AVA[] avas = rdn.getAssertion(); - // String relname = null; - StringBuffer relname = new StringBuffer(); - String s; - int i = 0; - - relname.append(encodeAVA(avas[i++])); - while (i < avas.length) { - s = encodeAVA(avas[i++]); - relname.append("+"); - relname.append(s); - } - ; - return relname.toString(); - } - - /** - * Converts a AVA to a Ldap v3 DN String (except in unicode). - * - * @param ava an AVA - * - * @return a Ldap v3 DN string (except in unicode). - * - * @exception IOException If an error is encountered during exception. - */ - public String encodeAVA(AVA ava) - throws IOException { - if (ava == null) { - return ""; - } - ObjectIdentifier oid = ava.getOid(); - DerValue value = ava.getValue(); - String keyword, valueStr; - - // get attribute name - - keyword = encodeOID(oid); - valueStr = encodeValue(value, oid); - - return keyword + "=" + valueStr; - } - - /** - * Converts an OID to a attribute keyword in a Ldap v3 DN string - * - either a keyword if known or a string of "1.2.3.4" syntax. - * - * @param oid a ObjectIdentifier - * - * @return a keyword to use in a Ldap V3 DN string. - * - * @exception IOException if an error is encountered during conversion. - */ - public String encodeOID(ObjectIdentifier oid) - throws IOException { - String keyword = attrMap.getName(oid); - if (keyword == null) { - if (acceptUnknownOids) - keyword = oid.toString(); - else - throw new IOException("Unknown OID"); - } - return keyword; - } - - /** - * Converts a value as a DerValue to a string in a Ldap V3 DN String. - * If the value cannot be converted to a string it will be encoded in - * octothorpe form. - * - * @param attrValue a value as a DerValue. - * @param oid OID for the attribute. - * @return a string for the value in a LDAP v3 DN String - * @exception IOException if an error occurs during conversion. - */ - public String encodeValue(DerValue attrValue, ObjectIdentifier oid) - throws IOException { - /* - * Construct the value with as little copying and garbage - * production as practical. - */ - StringBuffer retval = new StringBuffer(30); - int i; - String temp = null; - AVAValueConverter valueConverter; - - X500NameAttrMap lAttrMap = attrMap; - - if (attrValue.tag == DerValue.tag_UTF8String) { - lAttrMap = X500NameAttrMap.getDirDefault(); - - } - - valueConverter = lAttrMap.getValueConverter(oid); - if (valueConverter == null) { - if (acceptUnknownOids) - valueConverter = new GenericValueConverter(); - else - throw new IOException( - "Unknown AVA type for encoding AVA value"); - } - - try { - temp = valueConverter.getAsString(attrValue); - - if (temp == null) { - // convert to octothorpe form. - byte data[] = attrValue.toByteArray(); - - retval.append('#'); - for (i = 0; i < data.length; i++) { - retval.append(hexDigits.charAt((data[i] >> 4) & 0x0f)); - retval.append(hexDigits.charAt(data[i] & 0x0f)); - } - - } else { - - retval.append(encodeString(temp)); - - } - } catch (IOException e) { - throw new IllegalArgumentException("malformed AVA DER Value"); - } - - return retval.toString(); - } - - /** - * converts a raw value string to a string in Ldap V3 DN string format. - * - * @param valueStr a 'raw' value string. - * @return a attribute value string in Ldap V3 DN string format. - */ - public String encodeString(String valueStr) { - int i, j; - int len; - StringBuffer retval = new StringBuffer(); - - /* - * generate string according to ldapv3 DN. escaping is used. - * Strings generated this way are acceptable by rfc1779 - * implementations. - */ - len = valueStr.length(); - - // get index of first space at the end of the string. - for (j = len - 1; j >= 0 && valueStr.charAt(j) == ' '; j--) - continue; - - // escape spaces at the beginning of the string. - for (i = 0; i <= j && valueStr.charAt(i) == ' '; i++) { - retval.append('\\'); - retval.append(valueStr.charAt(i)); - } - - // escape special characters in the middle of the string. - for (; i <= j; i++) { - if (valueStr.charAt(i) == '\\') { - retval.append('\\'); - retval.append(valueStr.charAt(i)); - } else if (specialChars.indexOf(valueStr.charAt(i)) != -1) { - retval.append('\\'); - retval.append(valueStr.charAt(i)); - } else if (valueStr.charAt(i) == '"') { - retval.append('\\'); - retval.append(valueStr.charAt(i)); - } else - retval.append(valueStr.charAt(i)); - } - - // esacape spaces at the end. - for (; i < valueStr.length(); i++) { - retval.append('\\'); - retval.append(' '); - } - - return retval.toString(); - } - - // - // public get/set methods - // - - /** - * gets the X500NameAttrMap used by the converter. - * - * @return X500NameAttrMap used by this converter. - */ - public X500NameAttrMap getAttrMap() { - return attrMap; - } - - /** - * returns true if the converter accepts unregistered attributes i.e. - * OIDS not in the X500NameAttrMap. - * - * @return true if converter converts attributes not in the - * X500NameAttrMap. - */ - public boolean getAcceptUnknownOids() { - return acceptUnknownOids; - } - - // - // private and protected variables - // - - protected X500NameAttrMap attrMap; - protected boolean acceptUnknownOids; - - // - // private and protected static variables & methods. - // - - protected static final String specialChars = ",+=<>#;"; - - protected static final String valueEndChars = "+,;>"; - protected static final String quotedEndChars = "\""; - protected static final String octoEndChars = " " + valueEndChars; - - /* - * Values that aren't printable strings are emitted as BER-encoded - * hex data. - */ - protected static final String hexDigits = "0123456789ABCDEFabcdef"; - - /** - * Parse a sequence of hex pairs, each pair a UTF8 byte to a java string. - * For example, "4C75C48D" is "Luc", the last c with caron. - */ - protected static char[] getStringFromHexpairs(char[] hexPairs) throws UnsupportedEncodingException { - try { - byte[] buffer = new byte[hexPairs.length / 2]; - - for (int i = 0; i < buffer.length; i++) { - buffer[i] = (byte) - ((Character.digit(hexPairs[i * 2], 16) << 4) + - Character.digit(hexPairs[i * 2 + 1], 16)); - } - - Charset charset = Charset.forName("UTF-8"); - CharsetDecoder decoder = charset.newDecoder(); - - CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); - - return Arrays.copyOfRange(charBuffer.array(), - charBuffer.arrayOffset(), charBuffer.arrayOffset() + charBuffer.limit()); - - } catch (UnsupportedCharsetException e) { - throw new UnsupportedEncodingException( - "No UTF8 byte to char converter to use for " + - "parsing LDAP DN String"); - - } catch (CharacterCodingException e) { - throw new IllegalArgumentException( - "Invalid hex pair in LDAP DN String."); - } - } -} |