From a1546b7027db2885da6c3a8756e1480b92a8fdb6 Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 1 Jul 2011 06:34:21 +0000 Subject: [PATCH] Renamed translator ItoopieTranslator -> Transl. Changed http into https. Added support storing ssl certs. Added a GUI for confirming/denying/overwriting certs. --- .../jsonrpc2/client/JSONRPC2Session.java | 14 ++- src/net/i2p/itoopie/Main.java | 17 +-- src/net/i2p/itoopie/TrayManager.java | 48 ++------ src/net/i2p/itoopie/gui/CertificateGUI.java | 109 +++++++++++++++++ src/net/i2p/itoopie/gui/Main.java | 22 ++-- .../{ItoopieTranslator.java => Transl.java} | 2 +- .../i2p/itoopie/i2pcontrol/JSONInterface.java | 19 +++ .../itoopie/security/CertificateHelper.java | 107 +++++++++++++++++ .../itoopie/security/CertificateManager.java | 111 +++++++++++------- src/net/i2p/itoopie/util/IsJar.java | 14 +++ src/net/i2p/itoopie/util/IsJarTester.java | 5 + 11 files changed, 365 insertions(+), 103 deletions(-) create mode 100644 src/net/i2p/itoopie/gui/CertificateGUI.java rename src/net/i2p/itoopie/i18n/{ItoopieTranslator.java => Transl.java} (90%) create mode 100644 src/net/i2p/itoopie/util/IsJar.java create mode 100644 src/net/i2p/itoopie/util/IsJarTester.java diff --git a/src/com/thetransactioncompany/jsonrpc2/client/JSONRPC2Session.java b/src/com/thetransactioncompany/jsonrpc2/client/JSONRPC2Session.java index e788e35fa..0e2bebe93 100644 --- a/src/com/thetransactioncompany/jsonrpc2/client/JSONRPC2Session.java +++ b/src/com/thetransactioncompany/jsonrpc2/client/JSONRPC2Session.java @@ -13,6 +13,13 @@ import java.util.regex.*; import javax.net.ssl.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import net.i2p.itoopie.i2pcontrol.JSONInterface; +import net.i2p.itoopie.security.CertificateHelper; +import net.i2p.itoopie.security.CertificateManager; + import com.thetransactioncompany.jsonrpc2.*; @@ -106,7 +113,11 @@ import com.thetransactioncompany.jsonrpc2.*; * @version 1.2 (2011-03-29) */ public class JSONRPC2Session { - + private static final Log _log; + + static { + _log = LogFactory.getLog(JSONRPC2Session.class); + } /** * The server URL, which protocol must be HTTP or HTTPS. @@ -428,6 +439,7 @@ public class JSONRPC2Session { public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; + try { SSLContext sc = SSLContext.getInstance("SSL"); diff --git a/src/net/i2p/itoopie/Main.java b/src/net/i2p/itoopie/Main.java index 49def1745..6185fa32d 100644 --- a/src/net/i2p/itoopie/Main.java +++ b/src/net/i2p/itoopie/Main.java @@ -6,6 +6,7 @@ package net.i2p.itoopie; import java.security.Security; +import javax.net.ssl.HttpsURLConnection; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; @@ -16,6 +17,7 @@ import org.apache.commons.logging.LogFactory; import com.thetransactioncompany.jsonrpc2.JSONRPC2Error; import net.i2p.itoopie.i2pcontrol.JSONInterface; +import net.i2p.itoopie.security.CertificateHelper; import net.i2p.itoopie.util.ConfigurationManager; /** @@ -27,6 +29,7 @@ public class Main { private TrayManager trayManager = null; private static ConfigurationManager _conf; private static Log _log; + public static final boolean isDebug = true; /** * Start the tray icon code (loads tray icon in the tray area). @@ -62,6 +65,7 @@ public class Main { System.setProperty("java.awt.headless", "false"); _conf = ConfigurationManager.getInstance(); _log = LogFactory.getLog(Main.class); + HttpsURLConnection.setDefaultHostnameVerifier(CertificateHelper.getHostnameVerifier()); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); @@ -75,20 +79,11 @@ public class Main { //log.log(Log.ERROR, null, ex); } - _conf.parseConfigStr("server-name=localhost"); - _conf.parseConfigStr("server-port=7656"); + _conf.parseConfigStr("server-name=127.0.0.1"); + _conf.parseConfigStr("server-port=5555"); _conf.parseConfigStr("server-target=jsonrpc"); - for (java.security.Provider p : Security.getProviders()){ - System.out.println("Provider: " + p.getName()); - } - for (String p : Security.getAlgorithms("KeyStore")){ - System.out.println("KeyStore algorithm: " + p); - } - for (String p : Security.getAlgorithms("Cipher")){ - System.out.println("Cipher algorithm: " + p); - } String str = null; try { diff --git a/src/net/i2p/itoopie/TrayManager.java b/src/net/i2p/itoopie/TrayManager.java index c6d7298b5..39282e4ac 100644 --- a/src/net/i2p/itoopie/TrayManager.java +++ b/src/net/i2p/itoopie/TrayManager.java @@ -11,10 +11,12 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; +import javax.swing.JOptionPane; import javax.swing.SwingWorker; -import net.i2p.itoopie.i18n.ItoopieTranslator; +import net.i2p.itoopie.i18n.Transl; import net.i2p.itoopie.util.BrowseException; +import net.i2p.itoopie.util.IsJar; /** * Manages the tray icon life. @@ -81,14 +83,12 @@ public class TrayManager { desiredHeight = 512; } - URL url = getClass().getResource("/resources/images/itoopie-"+desiredHeight+".png"); - Image image = Toolkit.getDefaultToolkit().getImage(url); - //Image image = Toolkit.getDefaultToolkit().getImage("resources/images/itoopie-"+desiredHeight+".png"); - return image; - } - - protected static String _(String s) { - return ItoopieTranslator._(s); + if (IsJar.isRunningJar()){ + URL url = getClass().getResource("/resources/images/itoopie-"+desiredHeight+".png"); + return Toolkit.getDefaultToolkit().getImage(url); + } else { + return Toolkit.getDefaultToolkit().getImage("resources/images/itoopie-"+desiredHeight+".png"); + } } @@ -99,7 +99,7 @@ public class TrayManager { public PopupMenu getMainMenu() { PopupMenu popup = new PopupMenu(); - MenuItem browserLauncher = new MenuItem(_("Launch I2P Browser")); + MenuItem browserLauncher = new MenuItem(Transl._("Launch I2P Browser")); browserLauncher.addActionListener(new ActionListener() { @Override @@ -119,25 +119,7 @@ public class TrayManager { }.execute(); } }); - MenuItem restartItem = new MenuItem(_("Restart I2P")); - restartItem.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent arg0) { - new SwingWorker() { - - @Override - protected Object doInBackground() throws Exception { - //RouterManager.restart(); - return null; - } - - }.execute(); - - } - - }); - MenuItem stopItem = new MenuItem(_("Stop I2P")); + MenuItem stopItem = new MenuItem(Transl._("Exit itoopie")); stopItem.addActionListener(new ActionListener() { @Override @@ -146,19 +128,13 @@ public class TrayManager { @Override protected Object doInBackground() throws Exception { - //RouterManager.shutDown(); + System.exit(0); return null; } - }.execute(); - } - }); - popup.add(browserLauncher); - popup.addSeparator(); - popup.add(restartItem); popup.add(stopItem); return popup; diff --git a/src/net/i2p/itoopie/gui/CertificateGUI.java b/src/net/i2p/itoopie/gui/CertificateGUI.java new file mode 100644 index 000000000..7535f0c03 --- /dev/null +++ b/src/net/i2p/itoopie/gui/CertificateGUI.java @@ -0,0 +1,109 @@ +package net.i2p.itoopie.gui; + +import javax.security.cert.X509Certificate; +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import net.i2p.itoopie.i18n.Transl; +import net.i2p.itoopie.security.CertificateHelper; +import net.i2p.itoopie.security.CertificateManager; + +public class CertificateGUI { + + public static void main(String[] args){ + System.out.println("Save new cert: " + saveNewCert(null,null)); + System.out.println("Overwrite cert: " + overwriteCert(null,null)); + } + + public static boolean saveNewCert(String hostname, X509Certificate cert){ + JFrame frame = new JFrame(); + + String title = Transl._("New remote host detected"); + String hostString = Transl._("Would you like permanently trust the certificate from the remote host " + hostname + "?"); + + String certName = "N/A"; + String certAlgo = "N/A"; + String certSerial = "N/A"; + String certThumb = "N/A"; + if (cert != null){ + certName = cert.getSubjectDN().getName(); + String certString = cert.getPublicKey().toString(); + certAlgo = certString.substring(0,certString.indexOf("\n")); + certSerial = String.valueOf(cert.getPublicKey().serialVersionUID); + certThumb = CertificateHelper.getThumbPrint(cert); + } + String certInfo = ""+Transl._("Certificate info") + "

" + + Transl._("Name: ") + certName + "
" + + Transl._("Algorithm: ") + certAlgo + "
" + + Transl._("Serial: ") + certSerial + "
" + + Transl._("SHA-1 ID-hash: ") + certThumb; + + String textContent = certInfo + "

" + hostString; + + int n = JOptionPane.showConfirmDialog( + frame, + textContent, + title, + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE); + + if (n == JOptionPane.YES_OPTION){ + CertificateManager.forcePutServerCert(hostname, CertificateHelper.convert(cert)); + return true; + } else { + return false; + } + } + + + public static boolean overwriteCert(String hostname, X509Certificate cert){ + JFrame frame = new JFrame(); + + String title = Transl._("Warning, new remote host detected"); + String hostString = Transl._("The certificate of " + hostname + " has changed!
" + + "Are you sure you like permanently trust the new certificate from the remote host?"); + + String certName = "N/A"; + String certAlgo = "N/A"; + String certSerial = "N/A"; + String certThumb = "N/A"; + if (cert != null){ + certName = cert.getSubjectDN().getName(); + String certString = cert.getPublicKey().toString(); + certAlgo = certString.substring(0,certString.indexOf("\n")); + certSerial = String.valueOf(cert.getPublicKey().serialVersionUID); + certThumb = CertificateHelper.getThumbPrint(cert); + } + String certInfo = ""+Transl._("Certificate info") + "

" + + Transl._("Name: ") + certName + "
" + + Transl._("Algorithm: ") + certAlgo + "
" + + Transl._("Serial: ") + certSerial + "
" + + Transl._("SHA-1 ID-hash: ") + certThumb; + + String textContent = certInfo + "

" + hostString; + + int n = JOptionPane.showConfirmDialog( + frame, + textContent, + title, + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE); + + if (n == JOptionPane.YES_OPTION){ + n = JOptionPane.showConfirmDialog( + frame, + Transl._("Are you sure that you trust the new certificate?"), + Transl._("Is that you final answer?"), + JOptionPane.YES_NO_OPTION, + JOptionPane.ERROR_MESSAGE); + if (n == JOptionPane.YES_OPTION){ + CertificateManager.forcePutServerCert(hostname, CertificateHelper.convert(cert)); + return true; // Confirmation positive + } else { + return false; // Confirmation negative + } + } else { + return false; // No + } + } +} diff --git a/src/net/i2p/itoopie/gui/Main.java b/src/net/i2p/itoopie/gui/Main.java index 75e89db6a..f129593d7 100644 --- a/src/net/i2p/itoopie/gui/Main.java +++ b/src/net/i2p/itoopie/gui/Main.java @@ -10,7 +10,7 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.SwingWorker; -import net.i2p.itoopie.i18n.ItoopieTranslator; +import net.i2p.itoopie.i18n.Transl; import net.i2p.itoopie.i2pcontrol.JSONInterface; import net.i2p.itoopie.util.BrowseException; @@ -50,35 +50,35 @@ public class Main { frame.getContentPane().setLayout(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JButton btnStop = new JButton(ItoopieTranslator._("Stop I2P")); + JButton btnStop = new JButton(Transl._("Stop I2P")); btnStop.setBounds(293, 91, 125, 25); frame.getContentPane().add(btnStop); - JLabel lblStop = new JLabel(ItoopieTranslator._("Push to stop I2P")); + JLabel lblStop = new JLabel(Transl._("Push to stop I2P")); lblStop.setBounds(293, 78, 125, 15); frame.getContentPane().add(lblStop); - JButton btnStart = new JButton(ItoopieTranslator._("Start I2P")); + JButton btnStart = new JButton(Transl._("Start I2P")); btnStart.setBounds(43, 91, 125, 25); frame.getContentPane().add(btnStart); - JLabel lblStart = new JLabel(ItoopieTranslator._("Push to start I2P")); + JLabel lblStart = new JLabel(Transl._("Push to start I2P")); lblStart.setBounds(42, 78, 125, 15); frame.getContentPane().add(lblStart); - JLabel lblGetRate = new JLabel(ItoopieTranslator._("Get bwSend rate")); + JLabel lblGetRate = new JLabel(Transl._("Get bwSend rate")); lblGetRate.setBounds(293, 172, 125, 15); frame.getContentPane().add(lblGetRate); - final JLabel lblDispRate = new JLabel(ItoopieTranslator._("Rate not update yet, push button.")); + final JLabel lblDispRate = new JLabel(Transl._("Rate not update yet, push button.")); lblDispRate.setBounds(0,255,450,15); frame.getContentPane().add(lblDispRate); - JButton btnGetRate = new JButton(ItoopieTranslator._("Update")); + JButton btnGetRate = new JButton(Transl._("Update")); btnGetRate.setBounds(293, 185, 125, 25); frame.getContentPane().add(btnGetRate); - JButton btnConnect = new JButton(ItoopieTranslator._("Connect")); + JButton btnConnect = new JButton(Transl._("Connect")); btnConnect.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { } @@ -86,7 +86,7 @@ public class Main { btnConnect.setBounds(43, 185, 125, 25); frame.getContentPane().add(btnConnect); - JLabel lblConnect = new JLabel(ItoopieTranslator._("Connect to I2P")); + JLabel lblConnect = new JLabel(Transl._("Connect to I2P")); lblConnect.setBounds(43, 172, 125, 15); frame.getContentPane().add(lblConnect); @@ -120,7 +120,7 @@ public class Main { @Override protected Object doInBackground() throws Exception { double rate = JSONInterface.getRateStat("bw.sendRate", 3600000L); - lblDispRate.setText(ItoopieTranslator._("Current bw.sendRate: " + rate)); + lblDispRate.setText(Transl._("Current bw.sendRate: " + rate)); return null; } }.execute(); diff --git a/src/net/i2p/itoopie/i18n/ItoopieTranslator.java b/src/net/i2p/itoopie/i18n/Transl.java similarity index 90% rename from src/net/i2p/itoopie/i18n/ItoopieTranslator.java rename to src/net/i2p/itoopie/i18n/Transl.java index 11125f00c..f6a1997b3 100644 --- a/src/net/i2p/itoopie/i18n/ItoopieTranslator.java +++ b/src/net/i2p/itoopie/i18n/Transl.java @@ -1,6 +1,6 @@ package net.i2p.itoopie.i18n; -public class ItoopieTranslator { +public class Transl { private static final String BUNDLE_NAME = "net.i2p.itoopie.messages"; diff --git a/src/net/i2p/itoopie/i2pcontrol/JSONInterface.java b/src/net/i2p/itoopie/i2pcontrol/JSONInterface.java index 8564e8667..507ef7eb9 100644 --- a/src/net/i2p/itoopie/i2pcontrol/JSONInterface.java +++ b/src/net/i2p/itoopie/i2pcontrol/JSONInterface.java @@ -48,6 +48,7 @@ public class JSONInterface{ _log.error("Bad URL: https://"+srvHost+":"+srvPort+"/"+srvTarget, e); } session = new JSONRPC2Session(srvURL); + session.trustAllCerts(true); } @@ -98,4 +99,22 @@ public class JSONInterface{ throw resp.getError(); } } + + @SuppressWarnings("unchecked") + public static String getServerCert(String str) throws JSONRPC2Error{ + + JSONRPC2Request req = new JSONRPC2Request("echo", incrNonce()); + @SuppressWarnings("rawtypes") + Map params = new HashMap(); + params.put("echo", str); + req.setParams(params); + + JSONRPC2Response resp = sendReq(req); + if (resp.indicatesSuccess()){ + Map inParams = (HashMap)resp.getResult(); + return (String) inParams.get("serverCert"); + } else { + throw resp.getError(); + } + } } diff --git a/src/net/i2p/itoopie/security/CertificateHelper.java b/src/net/i2p/itoopie/security/CertificateHelper.java index 5616a6ee2..de32ccc94 100644 --- a/src/net/i2p/itoopie/security/CertificateHelper.java +++ b/src/net/i2p/itoopie/security/CertificateHelper.java @@ -1,10 +1,21 @@ package net.i2p.itoopie.security; import java.io.ByteArrayInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.cert.CertificateEncodingException; + +import net.i2p.itoopie.gui.CertificateGUI; +import net.i2p.itoopie.i18n.Transl; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -31,4 +42,100 @@ public class CertificateHelper { return null; } + + // Converts to java.security + public static java.security.cert.X509Certificate convert(javax.security.cert.X509Certificate cert) { + try { + byte[] encoded = cert.getEncoded(); + ByteArrayInputStream bis = new ByteArrayInputStream(encoded); + java.security.cert.CertificateFactory cf + = java.security.cert.CertificateFactory.getInstance("X.509"); + return (java.security.cert.X509Certificate)cf.generateCertificate(bis); + } catch (java.security.cert.CertificateEncodingException e) { + } catch (javax.security.cert.CertificateEncodingException e) { + } catch (java.security.cert.CertificateException e) { + } + return null; + } + + // Converts to javax.security + public static javax.security.cert.X509Certificate convert(java.security.cert.X509Certificate cert) { + try { + byte[] encoded = cert.getEncoded(); + return javax.security.cert.X509Certificate.getInstance(encoded); + } catch (java.security.cert.CertificateEncodingException e) { + } catch (javax.security.cert.CertificateEncodingException e) { + } catch (javax.security.cert.CertificateException e) { + } + return null; + } + + + public static String getThumbPrint(javax.security.cert.X509Certificate cert){ + try { + return getThumbPrint(convert(cert)); + } catch (Exception e){ + return Transl._("Unable to create hash of the given cert, ") + cert; + } + } + + public static String getThumbPrint(java.security.cert.X509Certificate cert) + throws NoSuchAlgorithmException, CertificateEncodingException { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] der = null; + try { + der = cert.getEncoded(); + } catch (java.security.cert.CertificateEncodingException e) { + e.printStackTrace(); + } + md.update(der); + byte[] digest = md.digest(); + return hexify(digest); + + } + + private static String hexify (byte bytes[]) { + + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + StringBuffer buf = new StringBuffer(bytes.length * 2); + + for (int i = 0; i < bytes.length; ++i) { + buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]); + buf.append(hexDigits[bytes[i] & 0x0f]); + } + + return buf.toString(); + } + + + + + public static HostnameVerifier getHostnameVerifier(){ + return new HostnameVerifier(){ + + public boolean verify(String urlHostName, SSLSession session) { + String serverHost = session.getPeerHost(); + try { + javax.security.cert.X509Certificate[] certs = session.getPeerCertificateChain(); + + if (CertificateManager.contains(serverHost)){ + if (CertificateManager.verifyCert(serverHost, CertificateHelper.convert(certs[0]))){ + return true; // Remote host has provided valid certificate that is store locally. + } else { + // Remote host has provided a certificate that != the stored certificate for this host + return CertificateGUI.overwriteCert(serverHost, certs[0]); + } + } else { + // GUI, Add new host! new host + return CertificateGUI.saveNewCert(serverHost, certs[0]); + } + } catch (SSLPeerUnverifiedException e) { + _log.fatal("Remote host could not be verified, possibly due to using not using athentication"); + return false; + } + } + }; + } } diff --git a/src/net/i2p/itoopie/security/CertificateManager.java b/src/net/i2p/itoopie/security/CertificateManager.java index f37278f8c..2c13a429f 100644 --- a/src/net/i2p/itoopie/security/CertificateManager.java +++ b/src/net/i2p/itoopie/security/CertificateManager.java @@ -2,17 +2,21 @@ package net.i2p.itoopie.security; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; +import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.SignatureException; import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.TrustManager; @@ -37,39 +41,16 @@ public class CertificateManager { _log = LogFactory.getLog(CertificateManager.class); } - /** - * Export X509Certificate as a file. - * - * @param cert - X509Certificate to export - * @param file - Destination file for certificate - */ - @SuppressWarnings("unused") - private static void export(X509Certificate cert, File file) { + + public static boolean verifyCert(String storedCertAlias, X509Certificate cert){ try { - // Get the encoded form which is suitable for exporting - byte[] buf = cert.getEncoded(); - - FileOutputStream os = new FileOutputStream(file); - // Never write certificate in binary form. - if (false) { - // Write in binary form - os.write(buf); - } else { - // Write in text form - Writer wr = new OutputStreamWriter(os, Charset.forName("UTF-8")); - wr.write("-----BEGIN CERTIFICATE-----\n"); - wr.write(new sun.misc.BASE64Encoder().encode(buf)); - wr.write("\n-----END CERTIFICATE-----\n"); - wr.flush(); - } - os.close(); - } catch (CertificateEncodingException e) { - _log.error( - "Bad certificate, can't be base64 encoded as a X509Certificate", - e); - } catch (IOException e) { - _log.error("File " + file.getAbsolutePath().toString() - + " couldn't be written", e); + X509Certificate storedCert = (X509Certificate) getDefaultKeyStore().getCertificate(storedCertAlias); + storedCert.verify(cert.getPublicKey()); + return true; + } catch (KeyStoreException e) { + return false; // Was unable to read cert with given alias. Which is fine. + } catch (Exception e) { + return false; // Something is wrong with the provided key. } } @@ -91,11 +72,13 @@ public class CertificateManager { * @return - True if store was successful, false in other cases. */ public static boolean putServerCert(String name, X509Certificate cert) { + KeyStore ks = getDefaultKeyStore(); try { - if (getDefaultKeyStore().containsAlias(name)){ + if (ks.containsAlias(name)){ return false; } else { - getDefaultKeyStore().setCertificateEntry(name, cert); + ks.setCertificateEntry(name, cert); + saveKeyStore(ks); return true; } } catch (KeyStoreException e) { @@ -104,6 +87,26 @@ public class CertificateManager { } return false; } + + + /** + * Force store server X509Certificate under the name provided even if a certificate with the given alias already exists. + * + * @param name - Name of the certificate + * @param cert - X509Certificate to store + * @return - True if store was successful, false in other cases. + */ + public static boolean forcePutServerCert(String name, X509Certificate cert) { + KeyStore ks = getDefaultKeyStore(); + try { + ks.setCertificateEntry(name, cert); + saveKeyStore(ks); + return true; + } catch (KeyStoreException e) { + e.printStackTrace(); + } + return false; + } /** * Overwrite current X509Certificate with this name. Will only work if the @@ -114,11 +117,13 @@ public class CertificateManager { * @return - True if the overwrite was successful, false in other cases */ public static boolean overwriteServerCert(String name, X509Certificate cert){ + KeyStore ks = getDefaultKeyStore(); try { - if (getDefaultKeyStore().containsAlias(name)){ + if (ks.containsAlias(name)){ return false; } else { getDefaultKeyStore().setCertificateEntry(name, cert); + saveKeyStore(ks); return true; } } catch (KeyStoreException e) { @@ -153,13 +158,12 @@ public class CertificateManager { */ private static synchronized KeyStore getDefaultKeyStore(){ if (_ks == null){ - KeyStore ks = null; try { - ks = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + _ks = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); if ((new File(DEFAULT_KEYSTORE_LOCATION)).exists()){ InputStream is = new FileInputStream(DEFAULT_KEYSTORE_LOCATION); - ks.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray()); - return ks; + _ks.load(is, DEFAULT_KEYSTORE_PASSWORD.toCharArray()); + return _ks; } else { throw new IOException("KeyStore file " + DEFAULT_KEYSTORE_LOCATION + "wasn't readable"); } @@ -167,10 +171,10 @@ public class CertificateManager { // Ignore. Not an issue. Let's just create a new keystore instead. } try { - ks = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); - ks.load(null, DEFAULT_KEYSTORE_PASSWORD.toCharArray()); - ks.store(new FileOutputStream(DEFAULT_KEYSTORE_LOCATION), DEFAULT_KEYSTORE_PASSWORD.toCharArray()); - return ks; + _ks = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE); + _ks.load(null, DEFAULT_KEYSTORE_PASSWORD.toCharArray()); + saveKeyStore(_ks); + return _ks; } catch (Exception e){ // Log perhaps? } @@ -179,4 +183,25 @@ public class CertificateManager { return _ks; } } + + private static void saveKeyStore(KeyStore ks){ + try { + ks.store(new FileOutputStream(DEFAULT_KEYSTORE_LOCATION), DEFAULT_KEYSTORE_PASSWORD.toCharArray()); + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (CertificateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } diff --git a/src/net/i2p/itoopie/util/IsJar.java b/src/net/i2p/itoopie/util/IsJar.java new file mode 100644 index 000000000..10c4ddb45 --- /dev/null +++ b/src/net/i2p/itoopie/util/IsJar.java @@ -0,0 +1,14 @@ +package net.i2p.itoopie.util; + +public abstract class IsJar { + + public static boolean isRunningJar(){ + IsJarTester isJar = new IsJarTester(); + String className = isJar.getClass().getName().replace('.', '/'); + String classJar = isJar.getClass().getResource("/" + className + ".class").toString(); + if (classJar.startsWith("jar:")) + return true; + else + return false; + } +} diff --git a/src/net/i2p/itoopie/util/IsJarTester.java b/src/net/i2p/itoopie/util/IsJarTester.java new file mode 100644 index 000000000..cc0a93937 --- /dev/null +++ b/src/net/i2p/itoopie/util/IsJarTester.java @@ -0,0 +1,5 @@ +package net.i2p.itoopie.util; + +public class IsJarTester { + +}