mirror of
https://github.com/moparisthebest/davmail
synced 2024-12-13 19:22:22 -05:00
Implement file based (PKCS12 and JKS) client certificates in addition to smartcard support
git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@908 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
parent
1267621a98
commit
9e3a90d11b
@ -128,6 +128,9 @@ public final class Settings {
|
|||||||
SETTINGS.put("davmail.ssl.keystoreFile", "");
|
SETTINGS.put("davmail.ssl.keystoreFile", "");
|
||||||
SETTINGS.put("davmail.ssl.keystorePass", "");
|
SETTINGS.put("davmail.ssl.keystorePass", "");
|
||||||
SETTINGS.put("davmail.ssl.keyPass", "");
|
SETTINGS.put("davmail.ssl.keyPass", "");
|
||||||
|
SETTINGS.put("davmail.ssl.clientKeystoreType", "");
|
||||||
|
SETTINGS.put("davmail.ssl.clientKeystoreFile", "");
|
||||||
|
SETTINGS.put("davmail.ssl.clientKeystorePass", "");
|
||||||
SETTINGS.put("davmail.ssl.pkcs11Library", "");
|
SETTINGS.put("davmail.ssl.pkcs11Library", "");
|
||||||
SETTINGS.put("davmail.ssl.pkcs11Config", "");
|
SETTINGS.put("davmail.ssl.pkcs11Config", "");
|
||||||
|
|
||||||
|
@ -33,12 +33,14 @@ import javax.security.auth.callback.Callback;
|
|||||||
import javax.security.auth.callback.CallbackHandler;
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
import javax.security.auth.callback.PasswordCallback;
|
import javax.security.auth.callback.PasswordCallback;
|
||||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manual Socket Factory.
|
* Manual Socket Factory.
|
||||||
@ -66,12 +68,36 @@ public class DavGatewaySSLProtocolSocketFactory implements SecureProtocolSocketF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private KeyStore.ProtectionParameter getProtectionParameter(String password) {
|
||||||
|
if (password != null && password.length() > 0) {
|
||||||
|
// password provided: create a PasswordProtection
|
||||||
|
return new KeyStore.PasswordProtection(password.toCharArray());
|
||||||
|
} else {
|
||||||
|
// request password at runtime through a callback
|
||||||
|
return new KeyStore.CallbackHandlerProtection(new CallbackHandler() {
|
||||||
|
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
||||||
|
if (callbacks.length > 0 && callbacks[0] instanceof PasswordCallback) {
|
||||||
|
PasswordPromptDialog passwordPromptDialog = new PasswordPromptDialog(((PasswordCallback) callbacks[0]).getPrompt());
|
||||||
|
((PasswordCallback) callbacks[0]).setPassword(passwordPromptDialog.getPassword());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private SSLContext sslcontext;
|
private SSLContext sslcontext;
|
||||||
|
|
||||||
private SSLContext createSSLContext() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyManagementException, KeyStoreException {
|
private SSLContext createSSLContext() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyManagementException, KeyStoreException {
|
||||||
// PKCS11 client certificate settings
|
// PKCS11 client certificate settings
|
||||||
String pkcs11Library = Settings.getProperty("davmail.ssl.pkcs11Library");
|
String pkcs11Library = Settings.getProperty("davmail.ssl.pkcs11Library");
|
||||||
if (pkcs11Library != null && pkcs11Library.length() > 0) {
|
|
||||||
|
String clientKeystoreType = Settings.getProperty("davmail.ssl.clientKeystoreType");
|
||||||
|
// set default keystore type
|
||||||
|
if (clientKeystoreType == null || clientKeystoreType.length() == 0) {
|
||||||
|
clientKeystoreType = "PKCS11";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkcs11Library != null && pkcs11Library.length() > 0 && "PKCS11".equals(clientKeystoreType)) {
|
||||||
StringBuilder pkcs11Buffer = new StringBuilder();
|
StringBuilder pkcs11Buffer = new StringBuilder();
|
||||||
pkcs11Buffer.append("name=DavMail\n");
|
pkcs11Buffer.append("name=DavMail\n");
|
||||||
pkcs11Buffer.append("library=").append(pkcs11Library).append('\n');
|
pkcs11Buffer.append("library=").append(pkcs11Library).append('\n');
|
||||||
@ -83,16 +109,23 @@ public class DavGatewaySSLProtocolSocketFactory implements SecureProtocolSocketF
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(/*KeyManagerFactory.getDefaultAlgorithm()*/"NewSunX509");
|
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(/*KeyManagerFactory.getDefaultAlgorithm()*/"NewSunX509");
|
||||||
KeyStore.Builder scBuilder = KeyStore.Builder.newInstance("PKCS11", null,
|
|
||||||
new KeyStore.CallbackHandlerProtection(new CallbackHandler() {
|
ArrayList<KeyStore.Builder> keyStoreBuilders = new ArrayList<KeyStore.Builder>();
|
||||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
|
// PKCS11 (smartcard) keystore with password callback
|
||||||
if (callbacks.length > 0 && callbacks[0] instanceof PasswordCallback) {
|
KeyStore.Builder scBuilder = KeyStore.Builder.newInstance("PKCS11", null, getProtectionParameter(null));
|
||||||
PasswordPromptDialog passwordPromptDialog = new PasswordPromptDialog(((PasswordCallback) callbacks[0]).getPrompt());
|
keyStoreBuilders.add(scBuilder);
|
||||||
((PasswordCallback) callbacks[0]).setPassword(passwordPromptDialog.getPassword());
|
|
||||||
|
String clientKeystoreFile = Settings.getProperty("davmail.ssl.clientKeystoreFile");
|
||||||
|
String clientKeystorePass = Settings.getProperty("davmail.ssl.clientKeystorePass");
|
||||||
|
if (clientKeystoreFile != null && clientKeystoreFile.length() > 0
|
||||||
|
&& ("PKCS12".equals(clientKeystoreType) || "JKS".equals(clientKeystoreType))) {
|
||||||
|
// PKCS12 file based keystore
|
||||||
|
KeyStore.Builder fsBuilder = KeyStore.Builder.newInstance(clientKeystoreType, null,
|
||||||
|
new File(clientKeystoreFile), getProtectionParameter(clientKeystorePass));
|
||||||
|
keyStoreBuilders.add(fsBuilder);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}));
|
ManagerFactoryParameters keyStoreBuilderParameters = new KeyStoreBuilderParameters(keyStoreBuilders);
|
||||||
ManagerFactoryParameters keyStoreBuilderParameters = new KeyStoreBuilderParameters(scBuilder);
|
|
||||||
keyManagerFactory.init(keyStoreBuilderParameters);
|
keyManagerFactory.init(keyStoreBuilderParameters);
|
||||||
|
|
||||||
SSLContext context = SSLContext.getInstance("SSL");
|
SSLContext context = SSLContext.getInstance("SSL");
|
||||||
|
@ -29,6 +29,8 @@ import javax.swing.*;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DavMail settings frame
|
* DavMail settings frame
|
||||||
@ -67,6 +69,9 @@ public class SettingsFrame extends JFrame {
|
|||||||
JPasswordField keystorePassField;
|
JPasswordField keystorePassField;
|
||||||
JPasswordField keyPassField;
|
JPasswordField keyPassField;
|
||||||
|
|
||||||
|
JComboBox clientKeystoreTypeCombo;
|
||||||
|
JTextField clientKeystoreFileField;
|
||||||
|
JPasswordField clientKeystorePassField;
|
||||||
JTextField pkcs11LibraryField;
|
JTextField pkcs11LibraryField;
|
||||||
JTextArea pkcs11ConfigField;
|
JTextArea pkcs11ConfigField;
|
||||||
|
|
||||||
@ -257,20 +262,53 @@ public class SettingsFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected JPanel getSmartCardPanel() {
|
protected JPanel getSmartCardPanel() {
|
||||||
JPanel smartCardPanel = new JPanel(new GridLayout(2, 2));
|
JPanel clientKeystorePanel = new JPanel(new GridLayout(2, 1));
|
||||||
smartCardPanel.setBorder(BorderFactory.createTitledBorder(BundleMessage.format("UI_CLIENT_CERTIFICATE")));
|
clientKeystorePanel.setLayout(new BoxLayout(clientKeystorePanel, BoxLayout.Y_AXIS));
|
||||||
|
clientKeystorePanel.setBorder(BorderFactory.createTitledBorder(BundleMessage.format("UI_CLIENT_CERTIFICATE")));
|
||||||
|
|
||||||
|
clientKeystoreTypeCombo = new JComboBox(new String[]{"PKCS11", "JKS", "PKCS12"});
|
||||||
|
clientKeystoreTypeCombo.setSelectedItem(Settings.getProperty("davmail.ssl.clientKeystoreType"));
|
||||||
|
clientKeystoreFileField = new JTextField(Settings.getProperty("davmail.ssl.clientKeystoreFile"), 17);
|
||||||
|
clientKeystorePassField = new JPasswordField(Settings.getProperty("davmail.ssl.clientKeystorePass"), 15);
|
||||||
|
|
||||||
pkcs11LibraryField = new JTextField(Settings.getProperty("davmail.ssl.pkcs11Library"), 17);
|
pkcs11LibraryField = new JTextField(Settings.getProperty("davmail.ssl.pkcs11Library"), 17);
|
||||||
pkcs11ConfigField = new JTextArea(2, 17);
|
pkcs11ConfigField = new JTextArea(2, 17);
|
||||||
|
pkcs11ConfigField.setText(Settings.getProperty("davmail.ssl.pkcs11Config"));
|
||||||
pkcs11ConfigField.setBorder(pkcs11LibraryField.getBorder());
|
pkcs11ConfigField.setBorder(pkcs11LibraryField.getBorder());
|
||||||
pkcs11ConfigField.setFont(pkcs11LibraryField.getFont());
|
pkcs11ConfigField.setFont(pkcs11LibraryField.getFont());
|
||||||
|
|
||||||
addSettingComponent(smartCardPanel, BundleMessage.format("UI_PKCS11_LIBRARY"), pkcs11LibraryField,
|
JPanel clientKeystoreTypePanel = new JPanel(new GridLayout(1, 2));
|
||||||
BundleMessage.format("UI_PKCS11_LIBRARY_HELP"));
|
addSettingComponent(clientKeystoreTypePanel, BundleMessage.format("UI_CLIENT_KEY_STORE_TYPE"), clientKeystoreTypeCombo,
|
||||||
addSettingComponent(smartCardPanel, BundleMessage.format("UI_PKCS11_CONFIG"), pkcs11ConfigField,
|
BundleMessage.format("UI_CLIENT_KEY_STORE_TYPE_HELP"));
|
||||||
BundleMessage.format("UI_PKCS11_CONFIG_HELP"));
|
clientKeystorePanel.add(clientKeystoreTypePanel);
|
||||||
|
|
||||||
return smartCardPanel;
|
final JPanel cardPanel = new JPanel(new CardLayout());
|
||||||
|
clientKeystorePanel.add(cardPanel);
|
||||||
|
|
||||||
|
JPanel clientKeystoreFilePanel = new JPanel(new GridLayout(2, 2));
|
||||||
|
addSettingComponent(clientKeystoreFilePanel, BundleMessage.format("UI_CLIENT_KEY_STORE"), clientKeystoreFileField,
|
||||||
|
BundleMessage.format("UI_CLIENT_KEY_STORE_HELP"));
|
||||||
|
addSettingComponent(clientKeystoreFilePanel, BundleMessage.format("UI_CLIENT_KEY_STORE_PASSWORD"), clientKeystorePassField,
|
||||||
|
BundleMessage.format("UI_CLIENT_KEY_STORE_PASSWORD_HELP"));
|
||||||
|
cardPanel.add(clientKeystoreFilePanel, "PKCS12");
|
||||||
|
cardPanel.add(clientKeystoreFilePanel, "JKS");
|
||||||
|
|
||||||
|
JPanel pkcs11Panel = new JPanel(new GridLayout(2, 2));
|
||||||
|
addSettingComponent(pkcs11Panel, BundleMessage.format("UI_PKCS11_LIBRARY"), pkcs11LibraryField,
|
||||||
|
BundleMessage.format("UI_PKCS11_LIBRARY_HELP"));
|
||||||
|
addSettingComponent(pkcs11Panel, BundleMessage.format("UI_PKCS11_CONFIG"), pkcs11ConfigField,
|
||||||
|
BundleMessage.format("UI_PKCS11_CONFIG_HELP"));
|
||||||
|
cardPanel.add(pkcs11Panel, "PKCS11");
|
||||||
|
|
||||||
|
((CardLayout)cardPanel.getLayout()).show(cardPanel, (String) clientKeystoreTypeCombo.getSelectedItem());
|
||||||
|
|
||||||
|
clientKeystoreTypeCombo.addItemListener(new ItemListener() {
|
||||||
|
public void itemStateChanged(ItemEvent event) {
|
||||||
|
CardLayout cardLayout = (CardLayout) (cardPanel.getLayout());
|
||||||
|
cardLayout.show(cardPanel, (String) event.getItem());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return clientKeystorePanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JPanel getNetworkSettingsPanel() {
|
protected JPanel getNetworkSettingsPanel() {
|
||||||
@ -372,6 +410,7 @@ public class SettingsFrame extends JFrame {
|
|||||||
keystorePassField.setText(Settings.getProperty("davmail.ssl.keystorePass"));
|
keystorePassField.setText(Settings.getProperty("davmail.ssl.keystorePass"));
|
||||||
keyPassField.setText(Settings.getProperty("davmail.ssl.keyPass"));
|
keyPassField.setText(Settings.getProperty("davmail.ssl.keyPass"));
|
||||||
|
|
||||||
|
clientKeystoreTypeCombo.setSelectedItem(Settings.getProperty("davmail.ssl.clientKeystoreType"));
|
||||||
pkcs11LibraryField.setText(Settings.getProperty("davmail.ssl.pkcs11Library"));
|
pkcs11LibraryField.setText(Settings.getProperty("davmail.ssl.pkcs11Library"));
|
||||||
pkcs11ConfigField.setText(Settings.getProperty("davmail.ssl.pkcs11Config"));
|
pkcs11ConfigField.setText(Settings.getProperty("davmail.ssl.pkcs11Config"));
|
||||||
|
|
||||||
@ -463,6 +502,9 @@ public class SettingsFrame extends JFrame {
|
|||||||
Settings.setProperty("davmail.ssl.keystorePass", String.valueOf(keystorePassField.getPassword()));
|
Settings.setProperty("davmail.ssl.keystorePass", String.valueOf(keystorePassField.getPassword()));
|
||||||
Settings.setProperty("davmail.ssl.keyPass", String.valueOf(keyPassField.getPassword()));
|
Settings.setProperty("davmail.ssl.keyPass", String.valueOf(keyPassField.getPassword()));
|
||||||
|
|
||||||
|
Settings.setProperty("davmail.ssl.clientKeystoreType", (String) clientKeystoreTypeCombo.getSelectedItem());
|
||||||
|
Settings.setProperty("davmail.ssl.clientKeystoreFile", clientKeystoreFileField.getText());
|
||||||
|
Settings.setProperty("davmail.ssl.clientKeystorePass", String.valueOf(clientKeystorePassField.getPassword()));
|
||||||
Settings.setProperty("davmail.ssl.pkcs11Library", pkcs11LibraryField.getText());
|
Settings.setProperty("davmail.ssl.pkcs11Library", pkcs11LibraryField.getText());
|
||||||
Settings.setProperty("davmail.ssl.pkcs11Config", pkcs11ConfigField.getText());
|
Settings.setProperty("davmail.ssl.pkcs11Config", pkcs11ConfigField.getText());
|
||||||
|
|
||||||
|
@ -180,10 +180,16 @@ UI_KEY_STORE_PASSWORD=Key store password:
|
|||||||
UI_KEY_STORE_PASSWORD_HELP=Key store password
|
UI_KEY_STORE_PASSWORD_HELP=Key store password
|
||||||
UI_KEY_STORE_TYPE=Key store type:
|
UI_KEY_STORE_TYPE=Key store type:
|
||||||
UI_KEY_STORE_TYPE_HELP=Choose key store type
|
UI_KEY_STORE_TYPE_HELP=Choose key store type
|
||||||
|
UI_CLIENT_KEY_STORE=Client key store:
|
||||||
|
UI_CLIENT_KEY_STORE_HELP=SSL client certificate key store file path
|
||||||
|
UI_CLIENT_KEY_STORE_PASSWORD=Client key store password:
|
||||||
|
UI_CLIENT_KEY_STORE_PASSWORD_HELP=Client key store password, leave empty for runtime prompt
|
||||||
|
UI_CLIENT_KEY_STORE_TYPE=Client key store type:
|
||||||
|
UI_CLIENT_KEY_STORE_TYPE_HELP=Choose client certificate key store type, choose PKCS11 for smartcard
|
||||||
UI_CLIENT_CERTIFICATE=Client Certificate
|
UI_CLIENT_CERTIFICATE=Client Certificate
|
||||||
UI_PKCS11_LIBRARY=PKCS11 library
|
UI_PKCS11_LIBRARY=PKCS11 library:
|
||||||
UI_PKCS11_LIBRARY_HELP=PKCS11 (smartcard) library path (.so or .dll)
|
UI_PKCS11_LIBRARY_HELP=PKCS11 (smartcard) library path (.so or .dll)
|
||||||
UI_PKCS11_CONFIG=PKCS11 config
|
UI_PKCS11_CONFIG=PKCS11 config:
|
||||||
UI_PKCS11_CONFIG_HELP=Optional additional PKCS11 settings (slot, nssArgs, ...)
|
UI_PKCS11_CONFIG_HELP=Optional additional PKCS11 settings (slot, nssArgs, ...)
|
||||||
UI_LAST_LOG=Last log
|
UI_LAST_LOG=Last log
|
||||||
UI_LAST_MESSAGE=Last message
|
UI_LAST_MESSAGE=Last message
|
||||||
|
@ -213,9 +213,9 @@ UI_VALID_FROM=Emis le
|
|||||||
UI_VALID_UNTIL=Expire le
|
UI_VALID_UNTIL=Expire le
|
||||||
UI_PASSWORD_PROMPT=DavMail : Entrer le mot de passe
|
UI_PASSWORD_PROMPT=DavMail : Entrer le mot de passe
|
||||||
UI_PKCS11_LIBRARY_HELP=Chemin de la librarie PKCS11 (carte à puce) (.so or .dll)
|
UI_PKCS11_LIBRARY_HELP=Chemin de la librarie PKCS11 (carte à puce) (.so or .dll)
|
||||||
UI_PKCS11_LIBRARY=Librairie PKCS11
|
UI_PKCS11_LIBRARY=Librairie PKCS11 :
|
||||||
UI_PKCS11_CONFIG_HELP=Configuration PKCS11 complémentaire optionnelle (slot, nssArgs, ...)
|
UI_PKCS11_CONFIG_HELP=Configuration PKCS11 complémentaire optionnelle (slot, nssArgs, ...)
|
||||||
UI_PKCS11_CONFIG=Configuration PKCS11
|
UI_PKCS11_CONFIG=Configuration PKCS11 :
|
||||||
UI_CLIENT_CERTIFICATE=Certificat client
|
UI_CLIENT_CERTIFICATE=Certificat client
|
||||||
UI_LOG_FILE_PATH=Chemin du fichier de traces :
|
UI_LOG_FILE_PATH=Chemin du fichier de traces :
|
||||||
LOG_GATEWAY_INTERRUPTED=Arrêt de la passerelle DavMail en cours
|
LOG_GATEWAY_INTERRUPTED=Arrêt de la passerelle DavMail en cours
|
||||||
@ -232,3 +232,9 @@ LOG_FOLDER_NOT_FOUND=Dossier {0} introuvable
|
|||||||
LOG_FOLDER_ACCESS_ERROR=Erreur lors de l''accès au dossier {0} : {1}
|
LOG_FOLDER_ACCESS_ERROR=Erreur lors de l''accès au dossier {0} : {1}
|
||||||
UI_OTP_PASSWORD_PROMPT=Mot de passe du jeton :
|
UI_OTP_PASSWORD_PROMPT=Mot de passe du jeton :
|
||||||
EXCEPTION_SESSION_EXPIRED=Session Exchange expirée
|
EXCEPTION_SESSION_EXPIRED=Session Exchange expirée
|
||||||
|
UI_CLIENT_KEY_STORE_TYPE=Type de stockage :
|
||||||
|
UI_CLIENT_KEY_STORE_TYPE_HELP=Choisir le type de stockage du certificat client, PKCS11 pour une carte à puce
|
||||||
|
UI_CLIENT_KEY_STORE=Fichier certificat client :
|
||||||
|
UI_CLIENT_KEY_STORE_HELP=Chemin du fichier contenant le certificat client SSL
|
||||||
|
UI_CLIENT_KEY_STORE_PASSWORD=Mot de passe certificat client :
|
||||||
|
UI_CLIENT_KEY_STORE_PASSWORD_HELP=Mot de passe du certificat client, laisser vide pour fournir le mot de passe mode interactif
|
Loading…
Reference in New Issue
Block a user