Renamed translator ItoopieTranslator -> Transl.
Changed http into https. Added support storing ssl certs. Added a GUI for confirming/denying/overwriting certs.
This commit is contained in:
@ -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");
|
||||
|
@ -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 {
|
||||
|
@ -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<Object, Object>() {
|
||||
|
||||
@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;
|
||||
|
109
src/net/i2p/itoopie/gui/CertificateGUI.java
Normal file
109
src/net/i2p/itoopie/gui/CertificateGUI.java
Normal file
@ -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 = "<html>"+Transl._("Certificate info") + "<br><br>" +
|
||||
Transl._("Name: ") + certName + "<br>" +
|
||||
Transl._("Algorithm: ") + certAlgo + "<br>" +
|
||||
Transl._("Serial: ") + certSerial + "<br>" +
|
||||
Transl._("SHA-1 ID-hash: ") + certThumb;
|
||||
|
||||
String textContent = certInfo + "<br><br>" + 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! <br>" +
|
||||
"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 = "<html>"+Transl._("Certificate info") + "<br><br>" +
|
||||
Transl._("Name: ") + certName + "<br>" +
|
||||
Transl._("Algorithm: ") + certAlgo + "<br>" +
|
||||
Transl._("Serial: ") + certSerial + "<br>" +
|
||||
Transl._("SHA-1 ID-hash: ") + certThumb;
|
||||
|
||||
String textContent = certInfo + "<br><br>" + 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
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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";
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
src/net/i2p/itoopie/util/IsJar.java
Normal file
14
src/net/i2p/itoopie/util/IsJar.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
5
src/net/i2p/itoopie/util/IsJarTester.java
Normal file
5
src/net/i2p/itoopie/util/IsJarTester.java
Normal file
@ -0,0 +1,5 @@
|
||||
package net.i2p.itoopie.util;
|
||||
|
||||
public class IsJarTester {
|
||||
|
||||
}
|
Reference in New Issue
Block a user