📄 interactivetrustmanager.java
字号:
//
// $Id: InteractiveTrustManager.java 612 2009-02-16 11:42:50Z etienne_sf $
//
// jupload - A file upload applet.
//
// Copyright 2007 The JUpload Team
//
// Created: 30.05.2007
// Creator: felfert
// Last modified: $Date: 2009-02-16 12:42:50 +0100 (lun., 16 févr. 2009) $
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
package wjhk.jupload2.upload.helper;
import java.awt.BorderLayout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.crypto.BadPaddingException;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import wjhk.jupload2.policies.UploadPolicy;
/**
* An implementation of {@link javax.net.ssl.X509TrustManager} which can operate
* in different modes. If mode is {@link #NONE}, then any server certificate is
* accepted and no certificate-based client authentication is performed. If mode
* is SERVER, then server certificates are verified and if verification is
* unsuccessful, a dialog is presented to the user, which allows accepting a
* certificate temporarily or permanently. If mode is CLIENT, then
* certificate-based client authentication is performed. Finally, there is a
* mode STRICT, which combines both SERVER and CLIENT modes.
*
* @author felfert
*/
public class InteractiveTrustManager implements X509TrustManager,
CallbackHandler {
/**
* Mode for accepting any certificate.
*/
public final static int NONE = 0;
/**
* Mode for verifying server certificate chains.
*/
public final static int SERVER = 1;
/**
* Mode for using client certificates.
*/
public final static int CLIENT = 2;
/**
* Mode for performing both client authentication and server cert
* verification.
*/
public final static int STRICT = SERVER + CLIENT;
private UploadPolicy uploadPolicy;
private int mode = STRICT;
private String hostname;
private final static String TS = ".truststore";
private final static String TSKEY = "javax.net.ssl.trustStore";
private final static String USERTS = System.getProperty("user.home")
+ File.separator + TS;
/**
* Absolute path of the truststore to use.
*/
private String tsname = null;
private String tspasswd = null;
private TrustManagerFactory tmf = null;
private KeyManagerFactory kmf = null;
/**
* The truststore for validation of server certificates
*/
private KeyStore ts = null;
/**
* The keystore for client certificates.
*/
private KeyStore ks = null;
private String getPassword(String storename) {
JPasswordField pwf = new JPasswordField(16);
JLabel l = new JLabel(String.format(this.uploadPolicy
.getString("itm_prompt_pass"), storename));
l.setLabelFor(pwf);
JPanel p = new JPanel(new BorderLayout(10, 0));
p.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
p.add(l, BorderLayout.LINE_START);
p.add(pwf, BorderLayout.LINE_END);
int res = JOptionPane.showConfirmDialog(null, p, String.format(
this.uploadPolicy.getString("itm_title_pass"), storename),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (res == JOptionPane.OK_OPTION)
return new String(pwf.getPassword());
return null;
}
/**
* @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
*/
public void handle(Callback[] callbacks)
throws UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof PasswordCallback) {
// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback) callbacks[i];
String pw = getPassword(pc.getPrompt());
pc.setPassword((pw == null) ? null : pw.toCharArray());
pw = null;
} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
/**
* Create a new instance.
*
* @param p The UploadPolicy to use for this instance.
* @param hostname
* @param passwd An optional password for the truststore.
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
* @throws CertificateException
* @throws IllegalArgumentException
* @throws UnrecoverableKeyException
*/
public InteractiveTrustManager(UploadPolicy p, String hostname,
String passwd) throws NoSuchAlgorithmException, KeyStoreException,
CertificateException, IllegalArgumentException,
UnrecoverableKeyException {
this.mode = p.getSslVerifyCert();
this.uploadPolicy = p;
if ((this.mode & SERVER) != 0) {
if (null == passwd)
// The default password as distributed by Sun.
passwd = "changeit";
this.tsname = System.getProperty(TSKEY);
if (null == this.tsname) {
// The default system-wide truststore
this.tsname = System.getProperty("java.home") + File.separator
+ "lib" + File.separator + "security" + File.separator
+ "cacerts";
// If the a user-specific truststore exists, it has precedence.
if (new File(USERTS).exists())
this.tsname = USERTS;
}
if (null == hostname || hostname.length() == 0)
throw new IllegalArgumentException(
"hostname may not be null or empty.");
this.hostname = hostname;
// Initialize the keystore only once, so that we can
// reuse it during the session
if (null == this.ts) {
this.ts = KeyStore.getInstance(KeyStore.getDefaultType());
while (true) {
try {
FileInputStream is = new FileInputStream(this.tsname);
this.ts.load(is, passwd.toCharArray());
is.close();
// need it later for eventual storing.
this.tspasswd = passwd;
break;
} catch (IOException e) {
if (e
.getMessage()
.equals(
"Keystore was tampered with, or password was incorrect")) {
passwd = getPassword(this.uploadPolicy
.getString("itm_tstore"));
if (null != passwd)
continue;
}
throw new KeyStoreException("Could not load truststore");
}
}
}
this.tmf = TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
this.tmf.init(this.ts);
}
if ((this.mode & CLIENT) != 0) {
String ksname = System.getProperty("javax.net.ssl.keyStore");
if (null == ksname)
ksname = System.getProperty("user.home") + File.separator
+ ".keystore";
String cpass = "changeit";
File f = new File(ksname);
if (!(f.exists() && f.isFile()))
throw new KeyStoreException("Keystore " + ksname
+ " does not exist.");
if (null == this.kmf) {
String kstype = ksname.toLowerCase().endsWith(".p12") ? "PKCS12"
: KeyStore.getDefaultType();
this.ks = KeyStore.getInstance(kstype);
while (true) {
try {
FileInputStream is = new FileInputStream(ksname);
this.ks.load(is, cpass.toCharArray());
is.close();
break;
} catch (IOException e) {
if ((e.getCause() instanceof BadPaddingException)
|| (e.getMessage()
.equals("Keystore was tampered with, or password was incorrect"))) {
cpass = getPassword("Keystore");
if (null != cpass)
continue;
}
throw new KeyStoreException("Could not load keystore: "
+ e.getMessage());
}
}
this.kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
this.kmf.init(this.ks, cpass.toCharArray());
}
}
}
/**
* Retrieve key managers.
*
* @return The current array of key managers.
*/
public KeyManager[] getKeyManagers() {
return ((this.mode & CLIENT) == 0) ? null : this.kmf.getKeyManagers();
}
/**
* Retrieve trust managers.
*
* @return The current array of trust managers
*/
public X509TrustManager[] getTrustManagers() {
return new X509TrustManager[] {
this
};
}
/**
* As this class is used on the client side only, The implementation of this
* method does nothing.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -