| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * Copyright 1999-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package com.sun.org.apache.xml.internal.security.utils; |
| |
| |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| |
| |
| /** |
| * |
| * @author $Author: mullan $ |
| */ |
| public class RFC2253Parser { |
| |
| |
| /** {@link java.util.logging} logging facility */ |
| /* static java.util.logging.Logger log = |
| java.util.logging.Logger.getLogger(RFC2253Parser.class.getName()); |
| */ |
| |
| static boolean _TOXML = true; |
| |
| /** |
| * Method rfc2253toXMLdsig |
| * |
| * @param dn |
| * @return normalized string |
| * |
| */ |
| public static String rfc2253toXMLdsig(String dn) { |
| |
| _TOXML = true; |
| |
| // Transform from RFC1779 to RFC2253 |
| String normalized = normalize(dn); |
| |
| return rfctoXML(normalized); |
| } |
| |
| /** |
| * Method xmldsigtoRFC2253 |
| * |
| * @param dn |
| * @return normalized string |
| */ |
| public static String xmldsigtoRFC2253(String dn) { |
| |
| _TOXML = false; |
| |
| // Transform from RFC1779 to RFC2253 |
| String normalized = normalize(dn); |
| |
| return xmltoRFC(normalized); |
| } |
| |
| /** |
| * Method normalize |
| * |
| * @param dn |
| * @return normalized string |
| */ |
| public static String normalize(String dn) { |
| |
| //if empty string |
| if ((dn == null) || dn.equals("")) { |
| return ""; |
| } |
| |
| try { |
| String _DN = semicolonToComma(dn); |
| StringBuffer sb = new StringBuffer(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| //for name component |
| for (int j = 0; (k = _DN.indexOf(",", j)) >= 0; j = k + 1) { |
| l += countQuotes(_DN, j, k); |
| |
| if ((k > 0) && (_DN.charAt(k - 1) != '\\') && (l % 2) != 1) { |
| sb.append(parseRDN(_DN.substring(i, k).trim()) + ","); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(parseRDN(trim(_DN.substring(i)))); |
| |
| return sb.toString(); |
| } catch (IOException ex) { |
| return dn; |
| } |
| } |
| |
| /** |
| * Method parseRDN |
| * |
| * @param str |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String parseRDN(String str) throws IOException { |
| |
| StringBuffer sb = new StringBuffer(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| for (int j = 0; (k = str.indexOf("+", j)) >= 0; j = k + 1) { |
| l += countQuotes(str, j, k); |
| |
| if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) != 1) { |
| sb.append(parseATAV(trim(str.substring(i, k))) + "+"); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(parseATAV(trim(str.substring(i)))); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method parseATAV |
| * |
| * @param str |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String parseATAV(String str) throws IOException { |
| |
| int i = str.indexOf("="); |
| |
| if ((i == -1) || ((i > 0) && (str.charAt(i - 1) == '\\'))) { |
| return str; |
| } |
| String attrType = normalizeAT(str.substring(0, i)); |
| // only normalize if value is a String |
| String attrValue = null; |
| if (attrType.charAt(0) >= '0' && attrType.charAt(0) <= '9') { |
| attrValue = str.substring(i + 1); |
| } else { |
| attrValue = normalizeV(str.substring(i + 1)); |
| } |
| |
| return attrType + "=" + attrValue; |
| |
| } |
| |
| /** |
| * Method normalizeAT |
| * |
| * @param str |
| * @return normalized string |
| */ |
| static String normalizeAT(String str) { |
| |
| String at = str.toUpperCase().trim(); |
| |
| if (at.startsWith("OID")) { |
| at = at.substring(3); |
| } |
| |
| return at; |
| } |
| |
| /** |
| * Method normalizeV |
| * |
| * @param str |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String normalizeV(String str) throws IOException { |
| |
| String value = trim(str); |
| |
| if (value.startsWith("\"")) { |
| StringBuffer sb = new StringBuffer(); |
| StringReader sr = new StringReader(value.substring(1, |
| value.length() - 1)); |
| int i = 0; |
| char c; |
| |
| for (; (i = sr.read()) > -1; ) { |
| c = (char) i; |
| |
| //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253 |
| if ((c == ',') || (c == '=') || (c == '+') || (c == '<') |
| || (c == '>') || (c == '#') || (c == ';')) { |
| sb.append('\\'); |
| } |
| |
| sb.append(c); |
| } |
| |
| value = trim(sb.toString()); |
| } |
| |
| if (_TOXML == true) { |
| if (value.startsWith("#")) { |
| value = '\\' + value; |
| } |
| } else { |
| if (value.startsWith("\\#")) { |
| value = value.substring(1); |
| } |
| } |
| |
| return value; |
| } |
| |
| /** |
| * Method rfctoXML |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String rfctoXML(String string) { |
| |
| try { |
| String s = changeLess32toXML(string); |
| |
| return changeWStoXML(s); |
| } catch (Exception e) { |
| return string; |
| } |
| } |
| |
| /** |
| * Method xmltoRFC |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String xmltoRFC(String string) { |
| |
| try { |
| String s = changeLess32toRFC(string); |
| |
| return changeWStoRFC(s); |
| } catch (Exception e) { |
| return string; |
| } |
| } |
| |
| /** |
| * Method changeLess32toRFC |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeLess32toRFC(String string) throws IOException { |
| |
| StringBuffer sb = new StringBuffer(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| char c; |
| |
| for (; (i = sr.read()) > -1; ) { |
| c = (char) i; |
| |
| if (c == '\\') { |
| sb.append(c); |
| |
| char c1 = (char) sr.read(); |
| char c2 = (char) sr.read(); |
| |
| //65 (A) 97 (a) |
| if ((((c1 >= 48) && (c1 <= 57)) || ((c1 >= 65) && (c1 <= 70)) || ((c1 >= 97) && (c1 <= 102))) |
| && (((c2 >= 48) && (c2 <= 57)) |
| || ((c2 >= 65) && (c2 <= 70)) |
| || ((c2 >= 97) && (c2 <= 102)))) { |
| char ch = (char) Byte.parseByte("" + c1 + c2, 16); |
| |
| sb.append(ch); |
| } else { |
| sb.append(c1); |
| sb.append(c2); |
| } |
| } else { |
| sb.append(c); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeLess32toXML |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeLess32toXML(String string) throws IOException { |
| |
| StringBuffer sb = new StringBuffer(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| |
| for (; (i = sr.read()) > -1; ) { |
| if (i < 32) { |
| sb.append('\\'); |
| sb.append(Integer.toHexString(i)); |
| } else { |
| sb.append((char) i); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeWStoXML |
| * |
| * @param string |
| * @return normalized string |
| * @throws IOException |
| */ |
| static String changeWStoXML(String string) throws IOException { |
| |
| StringBuffer sb = new StringBuffer(); |
| StringReader sr = new StringReader(string); |
| int i = 0; |
| char c; |
| |
| for (; (i = sr.read()) > -1; ) { |
| c = (char) i; |
| |
| if (c == '\\') { |
| char c1 = (char) sr.read(); |
| |
| if (c1 == ' ') { |
| sb.append('\\'); |
| |
| String s = "20"; |
| |
| sb.append(s); |
| } else { |
| sb.append('\\'); |
| sb.append(c1); |
| } |
| } else { |
| sb.append(c); |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method changeWStoRFC |
| * |
| * @param string |
| * @return normalized string |
| */ |
| static String changeWStoRFC(String string) { |
| |
| StringBuffer sb = new StringBuffer(); |
| int i = 0; |
| int k; |
| |
| for (int j = 0; (k = string.indexOf("\\20", j)) >= 0; j = k + 3) { |
| sb.append(trim(string.substring(i, k)) + "\\ "); |
| |
| i = k + 3; |
| } |
| |
| sb.append(string.substring(i)); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Method semicolonToComma |
| * |
| * @param str |
| * @return normalized string |
| */ |
| static String semicolonToComma(String str) { |
| return removeWSandReplace(str, ";", ","); |
| } |
| |
| /** |
| * Method removeWhiteSpace |
| * |
| * @param str |
| * @param symbol |
| * @return normalized string |
| */ |
| static String removeWhiteSpace(String str, String symbol) { |
| return removeWSandReplace(str, symbol, symbol); |
| } |
| |
| /** |
| * Method removeWSandReplace |
| * |
| * @param str |
| * @param symbol |
| * @param replace |
| * @return normalized string |
| */ |
| static String removeWSandReplace(String str, String symbol, String replace) { |
| |
| StringBuffer sb = new StringBuffer(); |
| int i = 0; |
| int l = 0; |
| int k; |
| |
| for (int j = 0; (k = str.indexOf(symbol, j)) >= 0; j = k + 1) { |
| l += countQuotes(str, j, k); |
| |
| if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) != 1) { |
| sb.append(trim(str.substring(i, k)) + replace); |
| |
| i = k + 1; |
| l = 0; |
| } |
| } |
| |
| sb.append(trim(str.substring(i))); |
| |
| return sb.toString(); |
| } |
| |
| /** |
| * Returns the number of Quotation from i to j |
| * |
| * @param s |
| * @param i |
| * @param j |
| * @return number of quotes |
| */ |
| private static int countQuotes(String s, int i, int j) { |
| |
| int k = 0; |
| |
| for (int l = i; l < j; l++) { |
| if (s.charAt(l) == '"') { |
| k++; |
| } |
| } |
| |
| return k; |
| } |
| |
| //only for the end of a space character occurring at the end of the string from rfc2253 |
| |
| /** |
| * Method trim |
| * |
| * @param str |
| * @return the string |
| */ |
| static String trim(String str) { |
| |
| String trimed = str.trim(); |
| int i = str.indexOf(trimed) + trimed.length(); |
| |
| if ((str.length() > i) && trimed.endsWith("\\") |
| &&!trimed.endsWith("\\\\")) { |
| if (str.charAt(i) == ' ') { |
| trimed = trimed + " "; |
| } |
| } |
| |
| return trimed; |
| } |
| |
| /** |
| * Method main |
| * |
| * @param args |
| * @throws Exception |
| */ |
| public static void main(String[] args) throws Exception { |
| |
| testToXML("CN=\"Steve, Kille\", O=Isode Limited, C=GB"); |
| testToXML("CN=Steve Kille , O=Isode Limited,C=GB"); |
| testToXML("\\ OU=Sales+CN=J. Smith,O=Widget Inc.,C=US\\ \\ "); |
| testToXML("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB"); |
| testToXML("CN=Before\\0DAfter,O=Test,C=GB"); |
| testToXML("CN=\"L. Eagle,O=Sue, = + < > # ;Grabbit and Runn\",C=GB"); |
| testToXML("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB"); |
| |
| { |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append('L'); |
| sb.append('u'); |
| sb.append('\uc48d'); |
| sb.append('i'); |
| sb.append('\uc487'); |
| |
| String test7 = "SN=" + sb.toString(); |
| |
| testToXML(test7); |
| } |
| |
| testToRFC("CN=\"Steve, Kille\", O=Isode Limited, C=GB"); |
| testToRFC("CN=Steve Kille , O=Isode Limited,C=GB"); |
| testToRFC("\\20OU=Sales+CN=J. Smith,O=Widget Inc.,C=US\\20\\20 "); |
| testToRFC("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB"); |
| testToRFC("CN=Before\\12After,O=Test,C=GB"); |
| testToRFC("CN=\"L. Eagle,O=Sue, = + < > # ;Grabbit and Runn\",C=GB"); |
| testToRFC("1.3.6.1.4.1.1466.0=\\#04024869,O=Test,C=GB"); |
| |
| { |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append('L'); |
| sb.append('u'); |
| sb.append('\uc48d'); |
| sb.append('i'); |
| sb.append('\uc487'); |
| |
| String test7 = "SN=" + sb.toString(); |
| |
| testToRFC(test7); |
| } |
| } |
| |
| /** Field i */ |
| static int counter = 0; |
| |
| /** |
| * Method test |
| * |
| * @param st |
| */ |
| static void testToXML(String st) { |
| |
| System.out.println("start " + counter++ + ": " + st); |
| System.out.println(" " + rfc2253toXMLdsig(st)); |
| System.out.println(""); |
| } |
| |
| /** |
| * Method testToRFC |
| * |
| * @param st |
| */ |
| static void testToRFC(String st) { |
| |
| System.out.println("start " + counter++ + ": " + st); |
| System.out.println(" " + xmldsigtoRFC2253(st)); |
| System.out.println(""); |
| } |
| } |