001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: AuthenticationUtil.java 8498 2007-08-03 18:33:00Z mpreston $
023: */
024: package com.bostechcorp.cbesb.ui.util;
025:
026: import java.io.BufferedReader;
027: import java.io.ByteArrayOutputStream;
028: import java.io.File;
029: import java.io.InputStream;
030: import java.io.InputStreamReader;
031: import java.io.OutputStream;
032: import java.io.PrintStream;
033: import java.io.StringReader;
034: import java.util.ArrayList;
035: import java.util.List;
036: import java.util.Vector;
037:
038: import org.apache.commons.logging.Log;
039: import org.apache.commons.logging.LogFactory;
040:
041: /*
042: * This is a utility class for the Authentication Manager functionality.
043: */
044: public class AuthenticationUtil {
045: protected static Log log = LogFactory
046: .getLog(AuthenticationUtil.class);
047: protected static String commandResult;
048: public static String MULTIPLE_FILE_SEPARATOR = " ;!; ";
049:
050: public static String getCommandResult() {
051: return commandResult;
052: }
053:
054: protected static String getKeyToolPath() {
055: String javaHome = System.getenv("JAVA_HOME");
056: if (javaHome != null) {
057: File path = new File(javaHome + File.separator + "bin"
058: + File.separator + "keytool");
059: return path.getAbsolutePath();
060: }
061: //JAVA_HOME is not set, hope keytool is in the system path
062: return "keytool";
063: }
064:
065: /**
066: * Generate a private/public key pair and self signed certificate and write it to a
067: * file in JKS format.
068: * This will overwite an existing file.
069: */
070: public static void generateKey(File jksFileToCreate, String dName,
071: String password) throws Exception {
072: if (jksFileToCreate.exists())
073: jksFileToCreate.delete();
074:
075: String command = getKeyToolPath()
076: + " -genkey -keyalg rsa -dname \"" + dName
077: + "\" -keypass " + password + " -storepass " + password
078: + " -keystore \"" + jksFileToCreate.getAbsolutePath()
079: + "\"" + " -keyalg \"RSA\"";
080: runKeyTool(command);
081: }
082:
083: /**
084: * Export a Certificate Signing Request from a private key jks file to a base-64 encoded
085: * export file.
086: */
087: public static void exportCertificateSigningRequest(File jksKeyFile,
088: String password, File exportFileToCreate) throws Exception {
089: String command = getKeyToolPath() + " -certreq -keypass "
090: + password + " -storepass " + password
091: + " -keystore \"" + jksKeyFile.getAbsolutePath() + "\""
092: + " -file \"" + exportFileToCreate.getAbsolutePath()
093: + "\"" + " -rfc";
094: runKeyTool(command);
095: }
096:
097: /**
098: * Export the public key certificate (or certificate chain) from a private key jks file
099: * to a base-64 encoded export file
100: */
101: public static void exportPublicKeyCertificate(File jksKeyFile,
102: String password, File exportFileToCreate) throws Exception {
103: String command = getKeyToolPath() + " -export -keypass "
104: + password + " -storepass " + password
105: + " -keystore \"" + jksKeyFile.getAbsolutePath() + "\""
106: + " -file \"" + exportFileToCreate.getAbsolutePath()
107: + "\"" + " -rfc";
108: runKeyTool(command);
109: }
110:
111: /**
112: * Import a base-64 encoded signed certificate chain into a jks key file.
113: * This replaces the existing certificate in the key file.
114: */
115: public static void importSignedCertificate(File jksKeyFile,
116: String password, File importFile, String preRequiredFiles)
117: throws Exception {
118:
119: importPreRequiredFiles(jksKeyFile, password,
120: processFileList(preRequiredFiles));
121: String command = getKeyToolPath() + " -import -keypass "
122: + password + " -storepass " + password
123: + " -keystore \"" + jksKeyFile.getAbsolutePath() + "\""
124: + " -file \"" + importFile.getAbsolutePath()
125: + "\" -noprompt";
126: runKeyTool(command);
127: }
128:
129: private static void importPreRequiredFiles(File jksKeyFile,
130: String password, File[] files) throws Exception {
131: if (files != null)
132: if (files.length != 0)
133: for (int i = 0; i < files.length; i++) {
134: String command = getKeyToolPath()
135: + " -import -alias chainCert" + i
136: + " -keypass " + password + " -storepass "
137: + password + " -keystore \""
138: + jksKeyFile.getAbsolutePath() + "\""
139: + " -file \"" + files[i].getPath()
140: + "\" -noprompt";
141: runKeyTool(command);
142: }
143: }
144:
145: private static File[] processFileList(String preRequiredFiles) {
146: String[] fileNames = preRequiredFiles
147: .split(MULTIPLE_FILE_SEPARATOR);
148: List<File> files = new ArrayList<File>();
149: if (fileNames.length != 0)
150: for (int i = 0; i < fileNames.length; i++) {
151: String fileName = fileNames[i].replaceAll("\r", "")
152: .replaceAll("\n", "");
153: if (!"".equals(fileName.trim())) {
154: File f = new File(fileName.trim());
155: if (f.exists())//making sure file really exists
156: {
157: files.add(f);
158: }
159: }
160: }
161: File[] ff = new File[files.size()];
162: return files.toArray(ff);
163: }
164:
165: /**
166: * Return a readable string summarizing a key file
167: * Used to "view" a key file.
168: */
169: public static String keyFileToString(File jksKeyFile,
170: String password) throws Exception {
171: String command = getKeyToolPath() + " -list -v -keypass "
172: + password + " -storepass " + password
173: + " -keystore \"" + jksKeyFile.getAbsolutePath() + "\"";
174: runKeyTool(command);
175:
176: return getCommandResult();
177: }
178:
179: /**
180: * Import a base-64 encoded certificate file into a trust store
181: */
182: public static void importTrustedCertificate(File jksTrustStoreFile,
183: String password, File importFile) throws Exception {
184: // construct an alias of the form certnnn that does not already exist in the truststore
185: String[] entries = {};
186: try {
187: entries = getTrustStoreEntries(jksTrustStoreFile, password);
188: } catch (Exception e) {
189: if (!e.toString().contains("file does not exist"))
190: throw e;
191: }
192: int maxVal = 0;
193: for (int i = 0; i < entries.length; i++) {
194: int val;
195: int index;
196: try {
197: if (entries[i].startsWith("cert")
198: && (index = entries[i].indexOf(' ')) > 0) {
199: val = Integer.parseInt(entries[i].substring(4,
200: index));
201: if (val > maxVal)
202: maxVal = val;
203: }
204: } catch (NumberFormatException nfe) {
205: //TODO
206: }
207: }
208: String alias = "cert" + (++maxVal);
209: // import the certificate
210: String command = getKeyToolPath() + " -import -keypass "
211: + password + " -storepass " + password
212: + " -keystore \"" + jksTrustStoreFile.getAbsolutePath()
213: + "\"" + " -alias " + alias + " -file \""
214: + importFile.getAbsolutePath() + "\"" + " -noprompt";
215: runKeyTool(command);
216: }
217:
218: /**
219: * Get a list of the entries in a trust store file. Use this to browse a trust file for
220: * exporting or deleting an entry.
221: */
222: public static String[] getTrustStoreEntries(File jksTrustStoreFile,
223: String password) throws Exception {
224: String[] result = { "" };
225: String command = getKeyToolPath() + " -list -v -keypass "
226: + password + " -storepass " + password
227: + " -keystore \"" + jksTrustStoreFile.getAbsolutePath()
228: + "\"";
229: runKeyTool(command);
230: Vector<String> aliases = new Vector<String>();
231: Vector<String> dNames = new Vector<String>();
232: BufferedReader br = new BufferedReader(new StringReader(
233: commandResult));
234: String line;
235: int index;
236: while ((line = br.readLine()) != null) {
237: if (line.startsWith("Alias")
238: && (index = line.indexOf(':')) > 0) {
239: aliases.add(line.substring(index + 2));
240: }
241: if (line.startsWith("Owner")
242: && (index = line.indexOf(':')) > 0) {
243: dNames.add(line.substring(index + 2));
244: }
245: }
246: int entries = aliases.size();
247: if (dNames.size() != entries)
248: throw new Exception("problem parsing file");
249: result = new String[entries];
250: for (int i = 0; i < entries; i++)
251: result[i] = aliases.elementAt(i) + " - "
252: + dNames.elementAt(i);
253: return result;
254: }
255:
256: /**
257: * Export a trusted certificate from a jks trust store file to a base-64 encoded export file.
258: * entryName should be an alias name in the truststore. Valid entries can be found with getTrustStoreEntries()
259: */
260: public static void exportTrustedCertificate(File jksTrustStoreFile,
261: String password, String entryName, File exportFileToCreate)
262: throws Exception {
263: String entryAlias;
264: int firstSpace = entryName.indexOf(' ');
265: if (firstSpace > 0)
266: entryAlias = entryName.substring(0, firstSpace);
267: else
268: entryAlias = entryName;
269: String command = getKeyToolPath() + " -export -keypass "
270: + password + " -storepass " + password
271: + " -keystore \"" + jksTrustStoreFile.getAbsolutePath()
272: + "\"" + " -file \""
273: + exportFileToCreate.getAbsolutePath() + "\"" + " -rfc"
274: + " -alias " + entryAlias;
275: runKeyTool(command);
276: }
277:
278: /**
279: * Delete a trusted certificate from a jks trust store file.
280: * entryName should be an alias name in the truststore. Valid entries can be found with getTrustStoreEntries()
281: */
282: public static void deleteTrustedCertificate(File jksTrustStoreFile,
283: String password, String entryName) throws Exception {
284: String entryAlias;
285: int firstSpace = entryName.indexOf(' ');
286: if (firstSpace > 0)
287: entryAlias = entryName.substring(0, firstSpace);
288: else
289: entryAlias = entryName;
290: String command = getKeyToolPath() + " -delete -keypass "
291: + password + " -storepass " + password
292: + " -keystore \"" + jksTrustStoreFile.getAbsolutePath()
293: + "\"" + " -alias " + entryAlias;
294: runKeyTool(command);
295: }
296:
297: /**
298: * Return a readable string summarizing the contents of a trust store file.
299: * Used to "view" a trust store.
300: */
301: public static String trustStoreFileToString(File jksTrustStoreFile,
302: String password) throws Exception {
303: return keyFileToString(jksTrustStoreFile, password);
304: }
305:
306: /**
307: * Return a human readable string summarizing the contents of a base-64 encoded export file.
308: * Use to "view" and export file.
309: */
310: public static String exportFileToString(File exportFile)
311: throws Exception {
312: String command = getKeyToolPath() + " -printcert -v -file \""
313: + exportFile.getAbsolutePath() + "\"";
314: runKeyTool(command);
315: return getCommandResult();
316: }
317:
318: protected class ProcessMonitor extends Thread {
319: BufferedReader br;
320: PrintStream ps;
321:
322: public ProcessMonitor(InputStream is, OutputStream os) {
323: this .br = new BufferedReader(new InputStreamReader(is));
324: this .ps = new PrintStream(os);
325: this .start();
326: }
327:
328: public void run() {
329: String line;
330: try {
331: while ((line = br.readLine()) != null)
332: ps.println(line);
333: } catch (Exception e) {
334: //TODO handle Exception
335: System.out.println("\n\nmonitor got " + e);
336: e.printStackTrace();
337: }
338: }
339: }
340:
341: protected static void runKeyTool(String cmd) throws Exception {
342: int ex = 1;
343: AuthenticationUtil inst = new AuthenticationUtil();
344: ByteArrayOutputStream baos = new ByteArrayOutputStream();
345: Runtime rt = Runtime.getRuntime();
346: try {
347: Process ktProc = rt.exec(cmd);
348: ProcessMonitor m1 = inst.new ProcessMonitor(ktProc
349: .getInputStream(), baos);
350: ProcessMonitor m2 = inst.new ProcessMonitor(ktProc
351: .getErrorStream(), baos);
352: OutputStream os = ktProc.getOutputStream();
353: PrintStream ps = new PrintStream(os);
354: ps.println("");
355: ps.flush();
356: ex = ktProc.waitFor();
357: m1.join();
358: m2.join();
359: commandResult = baos.toString();
360: } catch (Exception e) {
361: //TODO handle Exception
362: log.error("error processing certificate " + e, e);
363: }
364: if (ex != 0)
365: throw new Exception(commandResult);
366: }
367:
368: public static void main(String args[]) throws Exception {
369: System.out.println("AuthenticationUtil tester\n"
370: + " 1-Generate Private Key\n"
371: + " 2-Export Certificate Signing Request\n"
372: + " 3-Export Public Key Certificate\n"
373: + " 4-Import Signed Certificate\n"
374: + " 5-List key file contents\n"
375: + " 6-Import Trusted Certificate\n"
376: + " 7-Get Trust Store Entries\n"
377: + " 8-Export Trusted Certificate\n"
378: + " 9-Delete Trusted Certificate\n"
379: + " 10-List Trust Store Contents\n" + "option:");
380: BufferedReader bi = new BufferedReader(new InputStreamReader(
381: System.in));
382: int option = Integer.parseInt(bi.readLine());
383: switch (option) {
384: case 1: {
385: System.out.println("file:");
386: File jksFile = new File(bi.readLine());
387: System.out.println("password:");
388: String password = bi.readLine();
389: // make the dname
390: System.out.println("CN:");
391: String cn = bi.readLine();
392: System.out.println("OU:");
393: String ou = bi.readLine();
394: System.out.println("O:");
395: String o = bi.readLine();
396: System.out.println("L:");
397: String l = bi.readLine();
398: System.out.println("S:");
399: String s = bi.readLine();
400: System.out.println("C:");
401: String c = bi.readLine();
402: String dName = "CN=" + cn + " OU=" + ou + " O=" + o + " L="
403: + l + " S=" + s + " C=" + c;
404: AuthenticationUtil.generateKey(jksFile, dName, password);
405: System.out.println("\n\nresult:\n"
406: + AuthenticationUtil.getCommandResult());
407: }
408: break;
409:
410: case 2: {
411: System.out.println("key file:");
412: File jksFile = new File(bi.readLine());
413: System.out.println("password:");
414: String password = bi.readLine();
415: System.out.println("export file:");
416: File pemFile = new File(bi.readLine());
417: AuthenticationUtil.exportCertificateSigningRequest(jksFile,
418: password, pemFile);
419: System.out.println("\n\nresult:\n"
420: + AuthenticationUtil.getCommandResult());
421: }
422: break;
423:
424: case 3: {
425: System.out.println("key file:");
426: File jksFile = new File(bi.readLine());
427: System.out.println("password:");
428: String password = bi.readLine();
429: System.out.println("export file:");
430: File pemFile = new File(bi.readLine());
431: AuthenticationUtil.exportPublicKeyCertificate(jksFile,
432: password, pemFile);
433: System.out.println("\n\nresult:\n"
434: + AuthenticationUtil.getCommandResult());
435: }
436: break;
437:
438: case 4: {
439: System.out.println("key file:");
440: File jksFile = new File(bi.readLine());
441: System.out.println("password:");
442: String password = bi.readLine();
443: System.out.println("import file:");
444: File pemFile = new File(bi.readLine());
445: AuthenticationUtil.importSignedCertificate(jksFile,
446: password, pemFile, "");
447: System.out.println("\n\nresult:\n"
448: + AuthenticationUtil.getCommandResult());
449: }
450: break;
451:
452: case 5: {
453: System.out.println("key file:");
454: File jksFile = new File(bi.readLine());
455: System.out.println("password:");
456: String password = bi.readLine();
457: String content = AuthenticationUtil.keyFileToString(
458: jksFile, password);
459: System.out.println("\n\ncontent:\n" + content);
460: }
461: break;
462:
463: case 6: {
464: System.out.println("trust file:");
465: File jksFile = new File(bi.readLine());
466: System.out.println("password:");
467: String password = bi.readLine();
468: System.out.println("import file:");
469: File pemFile = new File(bi.readLine());
470: AuthenticationUtil.importTrustedCertificate(jksFile,
471: password, pemFile);
472: System.out.println("\n\nresult:\n"
473: + AuthenticationUtil.getCommandResult());
474: }
475: break;
476:
477: case 7: {
478: System.out.println("trust file:");
479: File jksFile = new File(bi.readLine());
480: System.out.println("password:");
481: String password = bi.readLine();
482: String entries[] = AuthenticationUtil.getTrustStoreEntries(
483: jksFile, password);
484: System.out.println("\n\ncontent:\n");
485: for (int i = 0; i < entries.length; i++)
486: System.out.println("entry[" + i + "]=" + entries[i]);
487: }
488: break;
489:
490: case 8: {
491: System.out.println("trust file:");
492: File jksFile = new File(bi.readLine());
493: System.out.println("password:");
494: String password = bi.readLine();
495: System.out.println("entry alias:");
496: String entry = bi.readLine();
497: System.out.println("export file:");
498: File pemFile = new File(bi.readLine());
499: AuthenticationUtil.exportTrustedCertificate(jksFile,
500: password, entry, pemFile);
501: System.out.println("\n\nresult:\n"
502: + AuthenticationUtil.getCommandResult());
503: }
504: break;
505:
506: case 9: {
507: System.out.println("trust file:");
508: File jksFile = new File(bi.readLine());
509: System.out.println("password:");
510: String password = bi.readLine();
511: System.out.println("entry alias:");
512: String entry = bi.readLine();
513: AuthenticationUtil.deleteTrustedCertificate(jksFile,
514: password, entry);
515: System.out.println("\n\nresult:\n"
516: + AuthenticationUtil.getCommandResult());
517: }
518: break;
519:
520: case 10: {
521: System.out.println("truststore file:");
522: File jksFile = new File(bi.readLine());
523: System.out.println("password:");
524: String password = bi.readLine();
525: String content = AuthenticationUtil.trustStoreFileToString(
526: jksFile, password);
527: System.out.println("\n\ncontent:\n" + content);
528: }
529: break;
530:
531: default:
532: System.out.println("bad option");
533: break;
534: }
535: }
536:
537: }
|