/* * 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: raul $ */ 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)); String 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.substring(0)) + 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(""); } }