Patch 2790299 by Mitchell V. Oliver: Add support for SSL to client connections

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@561 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2009-05-12 23:14:36 +00:00
parent da56920821
commit 3834476710
6 changed files with 137 additions and 20 deletions

View File

@ -1,11 +1,18 @@
package davmail;
import davmail.exception.DavMailException;
import davmail.ui.tray.DavGatewayTray;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
/**
* Generic abstract server common to SMTP and POP3 implementations
@ -15,6 +22,7 @@ public abstract class AbstractServer extends Thread {
private ServerSocket serverSocket;
public abstract String getProtocolName();
/**
* Server socket TCP port
*
@ -43,15 +51,55 @@ public abstract class AbstractServer extends Thread {
/**
* Bind server socket on defined port.
* @throws IOException unable to create server socket
*
* @throws DavMailException unable to create server socket
*/
public void bind() throws IOException {
public void bind() throws DavMailException {
String bindAddress = Settings.getProperty("davmail.bindAddress");
//noinspection SocketOpenedButNotSafelyClosed
if (bindAddress == null || bindAddress.length() == 0) {
serverSocket = new ServerSocket(this.port);
String keystoreFile = Settings.getProperty("davmail.ssl.keystoreFile");
ServerSocketFactory serverSocketFactory;
if (keystoreFile == null || keystoreFile.length() == 0) {
serverSocketFactory = ServerSocketFactory.getDefault();
} else {
serverSocket = new ServerSocket(this.port, 0, Inet4Address.getByName(bindAddress));
try {
// keystore for keys and certificates
// keystore and private keys should be password protected...
KeyStore keystore = KeyStore.getInstance(Settings.getProperty("davmail.ssl.keystoreType"));
keystore.load(new FileInputStream(keystoreFile),
Settings.getProperty("davmail.ssl.keystorePass").toCharArray());
// KeyManagerFactory to create key managers
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// initialize KMF to work with keystore
kmf.init(keystore, Settings.getProperty("davmail.ssl.keyPass").toCharArray());
// SSLContext is environment for implementing JSSE...
// create ServerSocketFactory
SSLContext sslc = SSLContext.getInstance("SSLv3");
// initialize sslc to work with key managers
sslc.init(kmf.getKeyManagers(), null, null);
// create ServerSocketFactory from sslc
serverSocketFactory = sslc.getServerSocketFactory();
} catch (IOException ex) {
throw new DavMailException("LOG_EXCEPTION_CREATING_SSL_SERVER_SOCKET", getProtocolName(), port, ex.getMessage() == null ? ex.toString() : ex.getMessage());
} catch (GeneralSecurityException ex) {
throw new DavMailException("LOG_EXCEPTION_CREATING_SSL_SERVER_SOCKET", getProtocolName(), port, ex.getMessage() == null ? ex.toString() : ex.getMessage());
}
}
try {
// create the server socket
if (bindAddress == null || bindAddress.length() == 0) {
serverSocket = serverSocketFactory.createServerSocket(port);
} else {
serverSocket = serverSocketFactory.createServerSocket(port, 0, Inet4Address.getByName(bindAddress));
}
} catch (IOException e) {
throw new DavMailException("LOG_SOCKET_BIND_FAILED", getProtocolName(), port);
}
}
@ -114,4 +162,3 @@ public abstract class AbstractServer extends Thread {
}
}
}

View File

@ -9,6 +9,7 @@ import davmail.ldap.LdapServer;
import davmail.pop.PopServer;
import davmail.smtp.SmtpServer;
import davmail.ui.tray.DavGatewayTray;
import davmail.exception.DavMailException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
@ -108,8 +109,8 @@ public class DavGateway {
server.bind();
server.start();
messages.add(new BundleMessage("LOG_PROTOCOL_PORT", server.getProtocolName(), server.getPort()));
} catch (BindException e) {
errorMessages.add(new BundleMessage("LOG_SOCKET_BIND_FAILED", server.getProtocolName(), server.getPort()));
} catch (DavMailException e) {
errorMessages.add(e.getBundleMessage());
} catch (IOException e) {
errorMessages.add(new BundleMessage("LOG_SOCKET_BIND_FAILED", server.getProtocolName(), server.getPort()));
}

View File

@ -65,6 +65,10 @@ public class Settings {
SETTINGS.put("davmail.proxyPassword", "");
SETTINGS.put("davmail.server", Boolean.FALSE.toString());
SETTINGS.put("davmail.server.certificate.hash", "");
SETTINGS.put("davmail.ssl.keystoreType", "");
SETTINGS.put("davmail.ssl.keystoreFile", "");
SETTINGS.put("davmail.ssl.keystorePass", "");
SETTINGS.put("davmail.ssl.keyPass", "");
// logging
SETTINGS.put("log4j.rootLogger", Priority.WARN.toString());

View File

@ -1,8 +1,8 @@
package davmail.ui;
import davmail.BundleMessage;
import davmail.DavGateway;
import davmail.Settings;
import davmail.BundleMessage;
import davmail.ui.tray.DavGatewayTray;
import org.apache.log4j.Level;
@ -43,6 +43,11 @@ public class SettingsFrame extends JFrame {
JTextField certHashField;
JCheckBox disableUpdateCheck;
JComboBox keystoreTypeCombo;
JTextField keystoreFileField;
JPasswordField keystorePassField;
JPasswordField keyPassField;
JComboBox rootLoggingLevelField;
JComboBox davmailLoggingLevelField;
JComboBox httpclientLoggingLevelField;
@ -206,6 +211,28 @@ public class SettingsFrame extends JFrame {
return proxyPanel;
}
protected JPanel getEncryptionPanel() {
JPanel encryptionPanel = new JPanel(new GridLayout(4, 2));
encryptionPanel.setBorder(BorderFactory.createTitledBorder(BundleMessage.format("UI_CERTIFICATE")));
keystoreTypeCombo = new JComboBox(new String[]{"JKS", "PKCS12"});
keystoreTypeCombo.setSelectedItem(Settings.getProperty("davmail.ssl.keystoreType"));
keystoreFileField = new JTextField(Settings.getProperty("davmail.ssl.keystoreFile"), 15);
keystorePassField = new JPasswordField(Settings.getProperty("davmail.ssl.keystorePass"), 15);
keyPassField = new JPasswordField(Settings.getProperty("davmail.ssl.keyPass"), 15);
addSettingComponent(encryptionPanel, BundleMessage.format("UI_KEY_STORE_TYPE"), keystoreTypeCombo,
BundleMessage.format("UI_KEY_STORE_TYPE_HELP"));
addSettingComponent(encryptionPanel, BundleMessage.format("UI_KEY_STORE"), keystoreFileField,
BundleMessage.format("UI_KEY_STORE_HELP"));
addSettingComponent(encryptionPanel, BundleMessage.format("UI_KEY_STORE_PASSWORD"), keystorePassField,
BundleMessage.format("UI_KEY_STORE_PASSWORD_HELP"));
addSettingComponent(encryptionPanel, BundleMessage.format("UI_KEY_PASSWORD"), keyPassField,
BundleMessage.format("UI_KEY_PASSWORD_HELP"));
return encryptionPanel;
}
public JPanel getNetworkSettingsPanel() {
JPanel networkSettingsPanel = new JPanel(new GridLayout(4, 2));
networkSettingsPanel.setBorder(BorderFactory.createTitledBorder(BundleMessage.format("UI_NETWORK")));
@ -285,6 +312,11 @@ public class SettingsFrame extends JFrame {
certHashField.setText(Settings.getProperty("davmail.server.certificate.hash"));
disableUpdateCheck.setSelected(Settings.getBooleanProperty(("davmail.disableUpdateCheck")));
keystoreTypeCombo.setSelectedItem(Settings.getProperty("davmail.ssl.keystoreType"));
keystoreFileField.setText(Settings.getProperty("davmail.ssl.keystoreFile"));
keystorePassField.setText(Settings.getProperty("davmail.ssl.keystorePass"));
keyPassField.setText(Settings.getProperty("davmail.ssl.keyPass"));
rootLoggingLevelField.setSelectedItem(Settings.getLoggingLevel("rootLogger"));
davmailLoggingLevelField.setSelectedItem(Settings.getLoggingLevel("davmail"));
httpclientLoggingLevelField.setSelectedItem(Settings.getLoggingLevel("org.apache.commons.httpclient"));
@ -324,6 +356,13 @@ public class SettingsFrame extends JFrame {
proxyPanel.add(new JPanel());
tabbedPane.add(BundleMessage.format("UI_TAB_PROXY"), proxyPanel);
JPanel encryptionPanel = new JPanel();
encryptionPanel.setLayout(new BoxLayout(encryptionPanel, BoxLayout.Y_AXIS));
encryptionPanel.add(getEncryptionPanel());
// empty panel
encryptionPanel.add(new JPanel());
tabbedPane.add(BundleMessage.format("UI_TAB_ENCRYPTION"), encryptionPanel);
advancedPanel.add(getNetworkSettingsPanel());
advancedPanel.add(getLoggingSettingsPanel());
@ -339,11 +378,11 @@ public class SettingsFrame extends JFrame {
public void actionPerformed(ActionEvent evt) {
// save options
Settings.setProperty("davmail.url", urlField.getText());
Settings.setProperty("davmail.popPort", popPortCheckBox.isSelected()?popPortField.getText():"");
Settings.setProperty("davmail.imapPort", imapPortCheckBox.isSelected()?imapPortField.getText():"");
Settings.setProperty("davmail.smtpPort", smtpPortCheckBox.isSelected()?smtpPortField.getText():"");
Settings.setProperty("davmail.caldavPort", caldavPortCheckBox.isSelected()?caldavPortField.getText():"");
Settings.setProperty("davmail.ldapPort", ldapPortCheckBox.isSelected()?ldapPortField.getText():"");
Settings.setProperty("davmail.popPort", popPortCheckBox.isSelected() ? popPortField.getText() : "");
Settings.setProperty("davmail.imapPort", imapPortCheckBox.isSelected() ? imapPortField.getText() : "");
Settings.setProperty("davmail.smtpPort", smtpPortCheckBox.isSelected() ? smtpPortField.getText() : "");
Settings.setProperty("davmail.caldavPort", caldavPortCheckBox.isSelected() ? caldavPortField.getText() : "");
Settings.setProperty("davmail.ldapPort", ldapPortCheckBox.isSelected() ? ldapPortField.getText() : "");
Settings.setProperty("davmail.keepDelay", keepDelayField.getText());
Settings.setProperty("davmail.sentKeepDelay", sentKeepDelayField.getText());
Settings.setProperty("davmail.caldavPastDelay", caldavPastDelayField.getText());
@ -357,6 +396,10 @@ public class SettingsFrame extends JFrame {
Settings.setProperty("davmail.allowRemote", String.valueOf(allowRemoteField.isSelected()));
Settings.setProperty("davmail.server.certificate.hash", certHashField.getText());
Settings.setProperty("davmail.disableUpdateCheck", String.valueOf(disableUpdateCheck.isSelected()));
Settings.setProperty("davmail.ssl.keystoreType", (String) keystoreTypeCombo.getSelectedItem());
Settings.setProperty("davmail.ssl.keystoreFile", keystoreFileField.getText());
Settings.setProperty("davmail.ssl.keystorePass", String.valueOf(keystorePassField.getPassword()));
Settings.setProperty("davmail.ssl.keyPass", String.valueOf(keyPassField.getPassword()));
Settings.setLoggingLevel("rootLogger", (Level) rootLoggingLevelField.getSelectedItem());
Settings.setLoggingLevel("davmail", (Level) davmailLoggingLevelField.getSelectedItem());
@ -381,8 +424,8 @@ public class SettingsFrame extends JFrame {
help.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
DesktopBrowser.browse("http://davmail.sourceforge.net");
}
DesktopBrowser.browse("http://davmail.sourceforge.net");
}
});
buttonPanel.add(ok);

View File

@ -20,6 +20,7 @@ LOG_EXCEPTION_GETTING_SOCKET_STREAMS=Exception while getting socket streams
LOG_EXCEPTION_LISTENING_FOR_CONNECTIONS=Exception while listening for connections
LOG_EXCEPTION_SENDING_ERROR_TO_CLIENT=Exception sending error to client
LOG_EXCEPTION_WAITING_SERVER_THREAD_DIE=Exception waiting for server thread to die
LOG_EXCEPTION_CREATING_SSL_SERVER_SOCKET=Unable to bind server socket for {0} on port {1,number,#}: Exception creating secured server socket : {2}
LOG_EXECUTE_FOLLOW_REDIRECTS=executeFollowRedirects({0})
LOG_EXECUTE_FOLLOW_REDIRECTS_COUNT=executeFollowRedirects: {0} redirectCount:{1}
LOG_EXTERNAL_CONNECTION_REFUSED=Connection from external client refused
@ -205,3 +206,13 @@ EXCEPTION_EXCHANGE_LOGIN_FAILED=Exchange login exception: {0}
UI_LAST_MESSAGE=Last message
UI_LAST_LOG=Last log
LOG_STARTING_DAVMAIL=Starting DavMail Gateway...
UI_KEY_STORE_TYPE=Key store type:
UI_KEY_STORE_TYPE_HELP=Choose key store type
UI_KEY_STORE=Key store:
UI_KEY_STORE_PASSWORD=Key store password:
UI_KEY_PASSWORD=Key password:
UI_KEY_STORE_HELP=SSL certificate key store file path
UI_KEY_STORE_PASSWORD_HELP=Key store password
UI_KEY_PASSWORD_HELP=SSL key password inside key store
UI_TAB_ENCRYPTION=Encryption
UI_CERTIFICATE=Certificate

View File

@ -89,7 +89,7 @@ UI_ABOUT=A propos...
UI_ABOUT_DAVMAIL=A propos de la Passerelle DavMail
UI_ABOUT_DAVMAIL_AUTHOR=<html><b>Passerelle DavMail</b><br>Par Mickaël Guessant<br><br>
UI_ACCEPT_CERTIFICATE=DavMail : Accepter le certificat ?
UI_ALLOW_REMOTE_CONNECTION=Autoriser les connexions distantes :
UI_ALLOW_REMOTE_CONNECTION=Autoriser connexions distantes :
UI_ALLOW_REMOTE_CONNECTION_HELP=Autoriser les connexions distantes à la passerelle (mode serveur)
UI_ANSWER_NO=n
UI_ANSWER_YES=o
@ -121,7 +121,7 @@ UI_IMAP_PORT=Port IMAP local :
UI_IMAP_PORT_HELP=Port IMAP local à configurer dans le client de messagerie
UI_ISSUED_BY=Emis par
UI_ISSUED_TO=Emis pour
UI_KEEP_DELAY=Délai de rétention dans la corbeille :
UI_KEEP_DELAY=Délai de rétention corbeille :
UI_KEEP_DELAY_HELP=Nombre de jours de conservation des messages dans la corbeille
UI_LATEST_VERSION=Dernière version disponible : {0} <br>Une nouvelle version de la Passerelle DavMail est disponible.<br><a href=\"http://sourceforge.net/project/platformdownload.php?group_id=184600\">Télécharcher la dernière version</a><br>
UI_LDAP_PORT=Port LDAP local :
@ -204,4 +204,15 @@ EXCEPTION_CONNECTION_FAILED=Connection OWA
EXCEPTION_EXCHANGE_LOGIN_FAILED=Exception lors de la connexion Exchange : {0}
LOG_STARTING_DAVMAIL=Démarrage de la passerelle DavMail...
UI_LAST_LOG=Dernière trace
UI_LAST_MESSAGE=Dernier message
UI_LAST_MESSAGE=Dernier message
LOG_EXCEPTION_CREATING_SSL_SERVER_SOCKET=Impossible d''ouvrir le port d''écoute {1,number,#} pour {0} : Erreur lors de la création du port d''écoute serveur sécurisé : {2}
UI_KEY_PASSWORD=Mot de passe clé :
UI_KEY_PASSWORD_HELP=Mot de passe clé SSL contenue dans le fichier des clés
UI_KEY_STORE=Fichier clés :
UI_KEY_STORE_HELP=Chemin du fichier contenant les clés et certificats SSL
UI_KEY_STORE_PASSWORD=Mot de passe fichier clés :
UI_KEY_STORE_PASSWORD_HELP=Mot de passe du fichier des clés
UI_KEY_STORE_TYPE=Type de fichier clés :
UI_KEY_STORE_TYPE_HELP=Choix du type de fichier de clés
UI_TAB_ENCRYPTION=Chiffrement
UI_CERTIFICATE=Certificat