blob: 06b81dafb601892dc02ea177a1048036ffc99506 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Copyright 1999-2004 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21package com.sun.org.apache.xml.internal.security.utils;
22
23
24
25import java.io.IOException;
26import java.io.StringReader;
27
28
29/**
30 *
31 * @author $Author: raul $
32 */
33public class RFC2253Parser {
34
35
36 /** {@link java.util.logging} logging facility */
37 /* static java.util.logging.Logger log =
38 java.util.logging.Logger.getLogger(RFC2253Parser.class.getName());
39 */
40
41 static boolean _TOXML = true;
42
43 /**
44 * Method rfc2253toXMLdsig
45 *
46 * @param dn
47 * @return normalized string
48 *
49 */
50 public static String rfc2253toXMLdsig(String dn) {
51
52 _TOXML = true;
53
54 // Transform from RFC1779 to RFC2253
55 String normalized = normalize(dn);
56
57 return rfctoXML(normalized);
58 }
59
60 /**
61 * Method xmldsigtoRFC2253
62 *
63 * @param dn
64 * @return normalized string
65 */
66 public static String xmldsigtoRFC2253(String dn) {
67
68 _TOXML = false;
69
70 // Transform from RFC1779 to RFC2253
71 String normalized = normalize(dn);
72
73 return xmltoRFC(normalized);
74 }
75
76 /**
77 * Method normalize
78 *
79 * @param dn
80 * @return normalized string
81 */
82 public static String normalize(String dn) {
83
84 //if empty string
85 if ((dn == null) || dn.equals("")) {
86 return "";
87 }
88
89 try {
90 String _DN = semicolonToComma(dn);
91 StringBuffer sb = new StringBuffer();
92 int i = 0;
93 int l = 0;
94 int k;
95
96 //for name component
97 for (int j = 0; (k = _DN.indexOf(",", j)) >= 0; j = k + 1) {
98 l += countQuotes(_DN, j, k);
99
100 if ((k > 0) && (_DN.charAt(k - 1) != '\\') && (l % 2) != 1) {
101 sb.append(parseRDN(_DN.substring(i, k).trim()) + ",");
102
103 i = k + 1;
104 l = 0;
105 }
106 }
107
108 sb.append(parseRDN(trim(_DN.substring(i))));
109
110 return sb.toString();
111 } catch (IOException ex) {
112 return dn;
113 }
114 }
115
116 /**
117 * Method parseRDN
118 *
119 * @param str
120 * @return normalized string
121 * @throws IOException
122 */
123 static String parseRDN(String str) throws IOException {
124
125 StringBuffer sb = new StringBuffer();
126 int i = 0;
127 int l = 0;
128 int k;
129
130 for (int j = 0; (k = str.indexOf("+", j)) >= 0; j = k + 1) {
131 l += countQuotes(str, j, k);
132
133 if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) != 1) {
134 sb.append(parseATAV(trim(str.substring(i, k))) + "+");
135
136 i = k + 1;
137 l = 0;
138 }
139 }
140
141 sb.append(parseATAV(trim(str.substring(i))));
142
143 return sb.toString();
144 }
145
146 /**
147 * Method parseATAV
148 *
149 * @param str
150 * @return normalized string
151 * @throws IOException
152 */
153 static String parseATAV(String str) throws IOException {
154
155 int i = str.indexOf("=");
156
157 if ((i == -1) || ((i > 0) && (str.charAt(i - 1) == '\\'))) {
158 return str;
159 }
160 String attrType = normalizeAT(str.substring(0, i));
161 String attrValue = normalizeV(str.substring(i + 1));
162
163 return attrType + "=" + attrValue;
164
165 }
166
167 /**
168 * Method normalizeAT
169 *
170 * @param str
171 * @return normalized string
172 */
173 static String normalizeAT(String str) {
174
175 String at = str.toUpperCase().trim();
176
177 if (at.startsWith("OID")) {
178 at = at.substring(3);
179 }
180
181 return at;
182 }
183
184 /**
185 * Method normalizeV
186 *
187 * @param str
188 * @return normalized string
189 * @throws IOException
190 */
191 static String normalizeV(String str) throws IOException {
192
193 String value = trim(str);
194
195 if (value.startsWith("\"")) {
196 StringBuffer sb = new StringBuffer();
197 StringReader sr = new StringReader(value.substring(1,
198 value.length() - 1));
199 int i = 0;
200 char c;
201
202 for (; (i = sr.read()) > -1; ) {
203 c = (char) i;
204
205 //the following char is defined at 4.Relationship with RFC1779 and LDAPv2 inrfc2253
206 if ((c == ',') || (c == '=') || (c == '+') || (c == '<')
207 || (c == '>') || (c == '#') || (c == ';')) {
208 sb.append('\\');
209 }
210
211 sb.append(c);
212 }
213
214 value = trim(sb.toString());
215 }
216
217 if (_TOXML == true) {
218 if (value.startsWith("#")) {
219 value = '\\' + value;
220 }
221 } else {
222 if (value.startsWith("\\#")) {
223 value = value.substring(1);
224 }
225 }
226
227 return value;
228 }
229
230 /**
231 * Method rfctoXML
232 *
233 * @param string
234 * @return normalized string
235 */
236 static String rfctoXML(String string) {
237
238 try {
239 String s = changeLess32toXML(string);
240
241 return changeWStoXML(s);
242 } catch (Exception e) {
243 return string;
244 }
245 }
246
247 /**
248 * Method xmltoRFC
249 *
250 * @param string
251 * @return normalized string
252 */
253 static String xmltoRFC(String string) {
254
255 try {
256 String s = changeLess32toRFC(string);
257
258 return changeWStoRFC(s);
259 } catch (Exception e) {
260 return string;
261 }
262 }
263
264 /**
265 * Method changeLess32toRFC
266 *
267 * @param string
268 * @return normalized string
269 * @throws IOException
270 */
271 static String changeLess32toRFC(String string) throws IOException {
272
273 StringBuffer sb = new StringBuffer();
274 StringReader sr = new StringReader(string);
275 int i = 0;
276 char c;
277
278 for (; (i = sr.read()) > -1; ) {
279 c = (char) i;
280
281 if (c == '\\') {
282 sb.append(c);
283
284 char c1 = (char) sr.read();
285 char c2 = (char) sr.read();
286
287 //65 (A) 97 (a)
288 if ((((c1 >= 48) && (c1 <= 57)) || ((c1 >= 65) && (c1 <= 70)) || ((c1 >= 97) && (c1 <= 102)))
289 && (((c2 >= 48) && (c2 <= 57))
290 || ((c2 >= 65) && (c2 <= 70))
291 || ((c2 >= 97) && (c2 <= 102)))) {
292 char ch = (char) Byte.parseByte("" + c1 + c2, 16);
293
294 sb.append(ch);
295 } else {
296 sb.append(c1);
297 sb.append(c2);
298 }
299 } else {
300 sb.append(c);
301 }
302 }
303
304 return sb.toString();
305 }
306
307 /**
308 * Method changeLess32toXML
309 *
310 * @param string
311 * @return normalized string
312 * @throws IOException
313 */
314 static String changeLess32toXML(String string) throws IOException {
315
316 StringBuffer sb = new StringBuffer();
317 StringReader sr = new StringReader(string);
318 int i = 0;
319
320 for (; (i = sr.read()) > -1; ) {
321 if (i < 32) {
322 sb.append('\\');
323 sb.append(Integer.toHexString(i));
324 } else {
325 sb.append((char) i);
326 }
327 }
328
329 return sb.toString();
330 }
331
332 /**
333 * Method changeWStoXML
334 *
335 * @param string
336 * @return normalized string
337 * @throws IOException
338 */
339 static String changeWStoXML(String string) throws IOException {
340
341 StringBuffer sb = new StringBuffer();
342 StringReader sr = new StringReader(string);
343 int i = 0;
344 char c;
345
346 for (; (i = sr.read()) > -1; ) {
347 c = (char) i;
348
349 if (c == '\\') {
350 char c1 = (char) sr.read();
351
352 if (c1 == ' ') {
353 sb.append('\\');
354
355 String s = "20";
356
357 sb.append(s);
358 } else {
359 sb.append('\\');
360 sb.append(c1);
361 }
362 } else {
363 sb.append(c);
364 }
365 }
366
367 return sb.toString();
368 }
369
370 /**
371 * Method changeWStoRFC
372 *
373 * @param string
374 * @return normalized string
375 */
376 static String changeWStoRFC(String string) {
377
378 StringBuffer sb = new StringBuffer();
379 int i = 0;
380 int k;
381
382 for (int j = 0; (k = string.indexOf("\\20", j)) >= 0; j = k + 3) {
383 sb.append(trim(string.substring(i, k)) + "\\ ");
384
385 i = k + 3;
386 }
387
388 sb.append(string.substring(i));
389
390 return sb.toString();
391 }
392
393 /**
394 * Method semicolonToComma
395 *
396 * @param str
397 * @return normalized string
398 */
399 static String semicolonToComma(String str) {
400 return removeWSandReplace(str, ";", ",");
401 }
402
403 /**
404 * Method removeWhiteSpace
405 *
406 * @param str
407 * @param symbol
408 * @return normalized string
409 */
410 static String removeWhiteSpace(String str, String symbol) {
411 return removeWSandReplace(str, symbol, symbol);
412 }
413
414 /**
415 * Method removeWSandReplace
416 *
417 * @param str
418 * @param symbol
419 * @param replace
420 * @return normalized string
421 */
422 static String removeWSandReplace(String str, String symbol, String replace) {
423
424 StringBuffer sb = new StringBuffer();
425 int i = 0;
426 int l = 0;
427 int k;
428
429 for (int j = 0; (k = str.indexOf(symbol, j)) >= 0; j = k + 1) {
430 l += countQuotes(str, j, k);
431
432 if ((k > 0) && (str.charAt(k - 1) != '\\') && (l % 2) != 1) {
433 sb.append(trim(str.substring(i, k)) + replace);
434
435 i = k + 1;
436 l = 0;
437 }
438 }
439
440 sb.append(trim(str.substring(i)));
441
442 return sb.toString();
443 }
444
445 /**
446 * Returns the number of Quotation from i to j
447 *
448 * @param s
449 * @param i
450 * @param j
451 * @return number of quotes
452 */
453 private static int countQuotes(String s, int i, int j) {
454
455 int k = 0;
456
457 for (int l = i; l < j; l++) {
458 if (s.charAt(l) == '"') {
459 k++;
460 }
461 }
462
463 return k;
464 }
465
466 //only for the end of a space character occurring at the end of the string from rfc2253
467
468 /**
469 * Method trim
470 *
471 * @param str
472 * @return the string
473 */
474 static String trim(String str) {
475
476 String trimed = str.trim();
477 int i = str.indexOf(trimed.substring(0)) + trimed.length();
478
479 if ((str.length() > i) && trimed.endsWith("\\")
480 &&!trimed.endsWith("\\\\")) {
481 if (str.charAt(i) == ' ') {
482 trimed = trimed + " ";
483 }
484 }
485
486 return trimed;
487 }
488
489 /**
490 * Method main
491 *
492 * @param args
493 * @throws Exception
494 */
495 public static void main(String[] args) throws Exception {
496
497 testToXML("CN=\"Steve, Kille\", O=Isode Limited, C=GB");
498 testToXML("CN=Steve Kille , O=Isode Limited,C=GB");
499 testToXML("\\ OU=Sales+CN=J. Smith,O=Widget Inc.,C=US\\ \\ ");
500 testToXML("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB");
501 testToXML("CN=Before\\0DAfter,O=Test,C=GB");
502 testToXML("CN=\"L. Eagle,O=Sue, = + < > # ;Grabbit and Runn\",C=GB");
503 testToXML("1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB");
504
505 {
506 StringBuffer sb = new StringBuffer();
507
508 sb.append('L');
509 sb.append('u');
510 sb.append('\uc48d');
511 sb.append('i');
512 sb.append('\uc487');
513
514 String test7 = "SN=" + sb.toString();
515
516 testToXML(test7);
517 }
518
519 testToRFC("CN=\"Steve, Kille\", O=Isode Limited, C=GB");
520 testToRFC("CN=Steve Kille , O=Isode Limited,C=GB");
521 testToRFC("\\20OU=Sales+CN=J. Smith,O=Widget Inc.,C=US\\20\\20 ");
522 testToRFC("CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB");
523 testToRFC("CN=Before\\12After,O=Test,C=GB");
524 testToRFC("CN=\"L. Eagle,O=Sue, = + < > # ;Grabbit and Runn\",C=GB");
525 testToRFC("1.3.6.1.4.1.1466.0=\\#04024869,O=Test,C=GB");
526
527 {
528 StringBuffer sb = new StringBuffer();
529
530 sb.append('L');
531 sb.append('u');
532 sb.append('\uc48d');
533 sb.append('i');
534 sb.append('\uc487');
535
536 String test7 = "SN=" + sb.toString();
537
538 testToRFC(test7);
539 }
540 }
541
542 /** Field i */
543 static int counter = 0;
544
545 /**
546 * Method test
547 *
548 * @param st
549 */
550 static void testToXML(String st) {
551
552 System.out.println("start " + counter++ + ": " + st);
553 System.out.println(" " + rfc2253toXMLdsig(st));
554 System.out.println("");
555 }
556
557 /**
558 * Method testToRFC
559 *
560 * @param st
561 */
562 static void testToRFC(String st) {
563
564 System.out.println("start " + counter++ + ": " + st);
565 System.out.println(" " + xmldsigtoRFC2253(st));
566 System.out.println("");
567 }
568}