Added a custom SSLProtocolSocketFactory to allow user to manually accept invalid or self signed certificates

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@150 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2008-10-31 17:12:30 +00:00
parent c92878eebd
commit cd2996f8a1
15 changed files with 614 additions and 177 deletions

View File

@ -1,5 +1,6 @@
package davmail;
import davmail.http.DavGatewaySSLProtocolSocketFactory;
import davmail.pop.PopServer;
import davmail.smtp.SmtpServer;
import davmail.tray.DavGatewayTray;
@ -57,25 +58,27 @@ public class DavGateway {
DavGatewayTray.error("Exception creating server socket", e);
}
// register custom SSL Socket factory
DavGatewaySSLProtocolSocketFactory.register();
}
public static void stop() {
if (smtpServer != null) {
smtpServer.close();
try {
smtpServer.join();
} catch (InterruptedException e) {
DavGatewayTray.warn("Exception waiting for listener to die", e);
}
}
if (popServer != null) {
popServer.close();
try {
popServer.join();
} catch (InterruptedException e) {
DavGatewayTray.warn("Exception waiting for listener to die", e);
}
}
}
public static void stop() {
if (smtpServer != null) {
smtpServer.close();
try {
smtpServer.join();
} catch (InterruptedException e) {
DavGatewayTray.warn("Exception waiting for listener to die", e);
}
}
if (popServer != null) {
popServer.close();
try {
popServer.join();
} catch (InterruptedException e) {
DavGatewayTray.warn("Exception waiting for listener to die", e);
}
}
}
}

View File

@ -55,6 +55,7 @@ public class Settings {
SETTINGS.put("davmail.proxyUser", "");
SETTINGS.put("davmail.proxyPassword", "");
SETTINGS.put("davmail.server", "false");
SETTINGS.put("davmail.server.certificate.hash", "");
save();
}
} catch (IOException e) {
@ -114,4 +115,11 @@ public class Settings {
String propertyValue = SETTINGS.getProperty(property);
return "true".equals(propertyValue);
}
public static synchronized void saveProperty(String property, String value) {
Settings.load();
Settings.setProperty(property, value);
Settings.save();
}
}

View File

@ -9,6 +9,21 @@ import java.awt.*;
* DavMail settings frame
*/
public class SettingsFrame extends JFrame {
protected JTextField urlField;
protected JTextField popPortField;
protected JTextField smtpPortField;
protected JTextField keepDelayField;
JCheckBox enableProxyField;
JTextField httpProxyField;
JTextField httpProxyPortField;
JTextField httpProxyUserField;
JTextField httpProxyPasswordField;
JCheckBox allowRemoteField;
JTextField bindAddressField;
JTextField certHashField;
protected void addSettingComponent(JPanel panel, String label, Component component) {
JLabel fieldLabel = new JLabel(label);
fieldLabel.setHorizontalAlignment(SwingConstants.RIGHT);
@ -16,22 +31,15 @@ public class SettingsFrame extends JFrame {
panel.add(component);
}
public SettingsFrame() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("DavMail Settings");
JTabbedPane tabbedPane = new JTabbedPane();
JPanel mainPanel = new JPanel(new GridLayout(2, 1));
protected JPanel getSettingsPanel() {
JPanel settingsPanel = new JPanel(new GridLayout(4, 2));
settingsPanel.setBorder(BorderFactory.createTitledBorder("Gateway settings"));
final JTextField urlField = new JTextField(Settings.getProperty("davmail.url"), 15);
urlField = new JTextField(Settings.getProperty("davmail.url"), 15);
urlField.setToolTipText("Base outlook web access URL");
final JTextField popPortField = new JTextField(Settings.getProperty("davmail.popPort"), 4);
final JTextField smtpPortField = new JTextField(Settings.getProperty("davmail.smtpPort"), 4);
final JTextField keepDelayField = new JTextField(Settings.getProperty("davmail.keepDelay"), 4);
popPortField = new JTextField(Settings.getProperty("davmail.popPort"), 4);
smtpPortField = new JTextField(Settings.getProperty("davmail.smtpPort"), 4);
keepDelayField = new JTextField(Settings.getProperty("davmail.keepDelay"), 4);
keepDelayField.setToolTipText("Number of days to keep messages in trash");
@ -39,19 +47,20 @@ public class SettingsFrame extends JFrame {
addSettingComponent(settingsPanel, "Local POP port: ", popPortField);
addSettingComponent(settingsPanel, "Local SMTP port: ", smtpPortField);
addSettingComponent(settingsPanel, "Keep Delay: ", keepDelayField);
return settingsPanel;
}
mainPanel.add(settingsPanel);
protected JPanel getProxyPanel() {
JPanel proxyPanel = new JPanel(new GridLayout(5, 2));
proxyPanel.setBorder(BorderFactory.createTitledBorder("Proxy settings"));
boolean enableProxy = Settings.getBooleanProperty("davmail.enableProxy");
final JCheckBox enableProxyField = new JCheckBox();
enableProxyField = new JCheckBox();
enableProxyField.setSelected(enableProxy);
final JTextField httpProxyField = new JTextField(Settings.getProperty("davmail.proxyHost"), 15);
final JTextField httpProxyPortField = new JTextField(Settings.getProperty("davmail.proxyPort"), 4);
final JTextField httpProxyUserField = new JTextField(Settings.getProperty("davmail.proxyUser"), 4);
final JTextField httpProxyPasswordField = new JPasswordField(Settings.getProperty("davmail.proxyPassword"), 4);
httpProxyField = new JTextField(Settings.getProperty("davmail.proxyHost"), 15);
httpProxyPortField = new JTextField(Settings.getProperty("davmail.proxyPort"), 4);
httpProxyUserField = new JTextField(Settings.getProperty("davmail.proxyUser"), 4);
httpProxyPasswordField = new JPasswordField(Settings.getProperty("davmail.proxyPassword"), 4);
httpProxyField.setEnabled(enableProxy);
httpProxyPortField.setEnabled(enableProxy);
@ -73,28 +82,66 @@ public class SettingsFrame extends JFrame {
addSettingComponent(proxyPanel, "Proxy port: ", httpProxyPortField);
addSettingComponent(proxyPanel, "Proxy user: ", httpProxyUserField);
addSettingComponent(proxyPanel, "Proxy password: ", httpProxyPasswordField);
return proxyPanel;
}
mainPanel.add(proxyPanel);
public JPanel getNetworkSettingsPanel() {
JPanel networkSettingsPanel = new JPanel(new GridLayout(3, 2));
networkSettingsPanel.setBorder(BorderFactory.createTitledBorder("Network settings"));
allowRemoteField = new JCheckBox();
allowRemoteField.setSelected(Settings.getBooleanProperty("davmail.allowRemote"));
allowRemoteField.setToolTipText("Allow remote connections to the gateway (server mode)");
bindAddressField = new JTextField(Settings.getProperty("davmail.bindAddress"), 15);
bindAddressField.setToolTipText("Bind only to the specified network address");
certHashField = new JTextField(Settings.getProperty("davmail.server.certificate.hash"), 15);
certHashField.setToolTipText("Manually accepted server certificate hash");
addSettingComponent(networkSettingsPanel, "Bind address: ", bindAddressField);
addSettingComponent(networkSettingsPanel, "Allow Remote Connections: ", allowRemoteField);
addSettingComponent(networkSettingsPanel, "Server certificate hash: ", certHashField);
return networkSettingsPanel;
}
public void reload() {
// reload settings in form
urlField.setText(Settings.getProperty("davmail.url"));
popPortField.setText(Settings.getProperty("davmail.popPort"));
smtpPortField.setText(Settings.getProperty("davmail.smtpPort"));
keepDelayField.setText(Settings.getProperty("davmail.keepDelay"));
allowRemoteField.setSelected(Settings.getBooleanProperty(("davmail.allowRemote")));
bindAddressField.setText(Settings.getProperty("davmail.bindAddress"));
boolean enableProxy = Settings.getBooleanProperty("davmail.enableProxy");
enableProxyField.setSelected(enableProxy);
httpProxyField.setEnabled(enableProxy);
httpProxyPortField.setEnabled(enableProxy);
httpProxyUserField.setEnabled(enableProxy);
httpProxyPasswordField.setEnabled(enableProxy);
httpProxyField.setText(Settings.getProperty("davmail.proxyHost"));
httpProxyPortField.setText(Settings.getProperty("davmail.proxyPort"));
httpProxyUserField.setText(Settings.getProperty("davmail.proxyUser"));
httpProxyPasswordField.setText(Settings.getProperty("davmail.proxyPassword"));
certHashField.setText(Settings.getProperty("davmail.server.certificate.hash"));
}
public SettingsFrame() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("DavMail Settings");
JTabbedPane tabbedPane = new JTabbedPane();
JPanel mainPanel = new JPanel(new GridLayout(2, 1));
mainPanel.add(getSettingsPanel());
mainPanel.add(getProxyPanel());
tabbedPane.add("Main", mainPanel);
JPanel advancedPanel = new JPanel();
advancedPanel.setLayout(new BorderLayout());
JPanel networkSettingsPanel = new JPanel(new GridLayout(2, 2));
networkSettingsPanel.setBorder(BorderFactory.createTitledBorder("Network settings"));
final JCheckBox allowRemoteField = new JCheckBox();
allowRemoteField.setSelected(Settings.getBooleanProperty("davmail.allowRemote"));
allowRemoteField.setToolTipText("Allow remote connections to the gateway (server mode)");
final JTextField bindAddressField = new JTextField(Settings.getProperty("davmail.bindAddress"), 15);
bindAddressField.setToolTipText("Bind only to the specified network address");
addSettingComponent(networkSettingsPanel, "Bind address: ", bindAddressField);
addSettingComponent(networkSettingsPanel, "Allow Remote Connections: ", allowRemoteField);
advancedPanel.add("North", networkSettingsPanel);
advancedPanel.add("North", getNetworkSettingsPanel());
tabbedPane.add("Advanced", advancedPanel);
@ -117,8 +164,9 @@ public class SettingsFrame extends JFrame {
Settings.setProperty("davmail.proxyPort", httpProxyPortField.getText());
Settings.setProperty("davmail.proxyUser", httpProxyUserField.getText());
Settings.setProperty("davmail.proxyPassword", httpProxyPasswordField.getText());
Settings.save();
Settings.setProperty("davmail.server.certificate.hash", certHashField.getText());
dispose();
Settings.save();
// restart listeners with new config
DavGateway.start();
}
@ -127,23 +175,7 @@ public class SettingsFrame extends JFrame {
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// reload settings in form
urlField.setText(Settings.getProperty("davmail.url"));
popPortField.setText(Settings.getProperty("davmail.popPort"));
smtpPortField.setText(Settings.getProperty("davmail.smtpPort"));
keepDelayField.setText(Settings.getProperty("davmail.keepDelay"));
allowRemoteField.setSelected(Settings.getBooleanProperty(("davmail.allowRemote")));
bindAddressField.setText(Settings.getProperty("davmail.bindAddress"));
boolean enableProxy = Settings.getBooleanProperty("davmail.allowRemote");
enableProxyField.setSelected(enableProxy);
httpProxyField.setEnabled(enableProxy);
httpProxyPortField.setEnabled(enableProxy);
httpProxyUserField.setEnabled(enableProxy);
httpProxyPasswordField.setEnabled(enableProxy);
httpProxyField.setText(Settings.getProperty("davmail.proxyHost"));
httpProxyPortField.setText(Settings.getProperty("davmail.proxyPort"));
httpProxyUserField.setText(Settings.getProperty("davmail.proxyUser"));
httpProxyPasswordField.setText(Settings.getProperty("davmail.proxyPassword"));
reload();
dispose();
}
});

View File

@ -1,7 +1,15 @@
package davmail.exchange;
import davmail.Settings;
import org.apache.commons.httpclient.*;
import davmail.http.DavGatewayHttpClientFactory;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.HttpURL;
import org.apache.commons.httpclient.HttpsURL;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
@ -12,13 +20,22 @@ import org.apache.webdav.lib.ResponseEntity;
import org.apache.webdav.lib.WebdavResource;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.SimpleTimeZone;
import java.util.Vector;
/**
* Exchange session through Outlook Web Access (DAV)
@ -65,91 +82,13 @@ public class ExchangeSession {
* Create an exchange session for the given URL.
* The session is not actually established until a call to login()
*/
public ExchangeSession() {
ExchangeSession() {
// SimpleDateFormat are not thread safe, need to create one instance for
// each session
dateParser = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
dateParser.setTimeZone(new SimpleTimeZone(0, "GMT"));
}
/**
* Update http client configuration (proxy)
*
* @param httpClient current Http client
*/
protected static void configureClient(HttpClient httpClient) {
// do not send basic auth automatically
httpClient.getState().setAuthenticationPreemptive(false);
boolean enableProxy = Settings.getBooleanProperty("davmail.enableProxy");
String proxyHost = null;
int proxyPort = 0;
String proxyUser = null;
String proxyPassword = null;
if (enableProxy) {
proxyHost = Settings.getProperty("davmail.proxyHost");
proxyPort = Settings.getIntProperty("davmail.proxyPort");
proxyUser = Settings.getProperty("davmail.proxyUser");
proxyPassword = Settings.getProperty("davmail.proxyPassword");
}
// configure proxy
if (proxyHost != null && proxyHost.length() > 0) {
httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
if (proxyUser != null && proxyUser.length() > 0) {
/* // Only available in newer HttpClient releases, not compatible with slide library
List authPrefs = new ArrayList();
authPrefs.add(AuthPolicy.BASIC);
httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY,authPrefs);
*/
// instead detect ntlm authentication (windows domain name in user name)
int backslashindex = proxyUser.indexOf("\\");
if (backslashindex > 0) {
httpClient.getState().setProxyCredentials(null, proxyHost,
new NTCredentials(proxyUser.substring(backslashindex + 1),
proxyPassword, null,
proxyUser.substring(0, backslashindex)));
} else {
httpClient.getState().setProxyCredentials(null, proxyHost,
new UsernamePasswordCredentials(proxyUser, proxyPassword));
}
}
}
}
public static void checkConfig() throws IOException {
try {
String url = Settings.getProperty("davmail.url");
// create an HttpClient instance
HttpClient httpClient = new HttpClient();
configureClient(httpClient);
// get webmail root url (will not follow redirects)
HttpMethod testMethod = new GetMethod(url);
testMethod.setFollowRedirects(false);
int status = httpClient.executeMethod(testMethod);
testMethod.releaseConnection();
LOGGER.debug("Test configuration status: " + status);
if (status != HttpStatus.SC_OK && status != HttpStatus.SC_UNAUTHORIZED
&& status != HttpStatus.SC_MOVED_TEMPORARILY) {
throw new IOException("Unable to connect to OWA at " + url + ", status code " +
status + ", check configuration");
}
} catch (UnknownHostException exc) {
LOGGER.error("DavMail configuration exception: \n Unknown host " + exc.getMessage(), exc);
throw new IOException("DavMail configuration exception: \n Unknown host " + exc.getMessage(), exc);
} catch (Exception exc) {
LOGGER.error("DavMail configuration exception: \n" + exc.getMessage(), exc);
throw new IOException("DavMail configuration exception: \n" + exc.getMessage(), exc);
}
}
/**
* Test authentication mode : form based or basic.
*
@ -159,15 +98,14 @@ public class ExchangeSession {
*/
protected boolean isBasicAuthentication(String url) throws IOException {
// create an HttpClient instance
HttpClient httpClient = new HttpClient();
configureClient(httpClient);
HttpClient httpClient = DavGatewayHttpClientFactory.getInstance();
HttpMethod testMethod = new GetMethod(url);
int status = httpClient.executeMethod(testMethod);
testMethod.releaseConnection();
return status == HttpStatus.SC_UNAUTHORIZED;
}
public void login(String userName, String password) throws IOException {
void login(String userName, String password) throws IOException {
try {
String url = Settings.getProperty("davmail.url");
@ -194,13 +132,24 @@ public class ExchangeSession {
// get the internal HttpClient instance
HttpClient httpClient = wdr.retrieveSessionInstance();
configureClient(httpClient);
DavGatewayHttpClientFactory.configureClient(httpClient);
// get webmail root url (will follow redirects)
// get webmail root url
// providing credentials
// manually follow redirect
HttpMethod initmethod = new GetMethod(url);
wdr.executeHttpRequestMethod(httpClient,
initmethod);
initmethod.setFollowRedirects(false);
httpClient.executeMethod(initmethod);
int redirectCount = 0;
while (redirectCount++ < 10 && initmethod.getStatusCode() == 302) {
initmethod.releaseConnection();
initmethod = new GetMethod(initmethod.getResponseHeader("Location").getValue());
initmethod.setFollowRedirects(false);
httpClient.executeMethod(initmethod);
}
if (initmethod.getStatusCode() == 302) {
throw new IOException("Maximum redirections reached");
}
// default destination is provided url
String destination = url;
@ -216,12 +165,12 @@ public class ExchangeSession {
loginFormReader = new BufferedReader(new InputStreamReader(initmethod.getResponseBodyAsStream()));
String line;
// skip to form action
final String FORM_ACTION = "<FORM action=\"";
final String FORM_ACTION = "<form action=\"";
final String DESTINATION_INPUT = "name=\"destination\" value=\"";
//noinspection StatementWithEmptyBody
while ((line = loginFormReader.readLine()) != null && line.indexOf(FORM_ACTION) == -1){}
while ((line = loginFormReader.readLine()) != null && line.toLowerCase().indexOf(FORM_ACTION) == -1){}
if (line != null) {
int start = line.indexOf(FORM_ACTION) + FORM_ACTION.length();
int start = line.toLowerCase().indexOf(FORM_ACTION) + FORM_ACTION.length();
int end = line.indexOf("\"", start);
logonMethodPath = line.substring(start, end);
//noinspection StatementWithEmptyBody
@ -232,6 +181,14 @@ public class ExchangeSession {
destination = line.substring(start, end);
}
}
// allow relative URLs
if (!logonMethodPath.startsWith("/")) {
String path = initmethod.getPath();
int end = path.lastIndexOf('/');
if (end >=0) {
logonMethodPath = path.substring(0, end+1) + logonMethodPath;
}
}
} catch (IOException e) {
LOGGER.error("Error parsing login form at " + initmethod.getPath());
} finally {
@ -264,7 +221,18 @@ public class ExchangeSession {
// User may be authenticated, get various session information
HttpMethod method = new GetMethod(destination);
int status = wdr.executeHttpRequestMethod(httpClient, method);
method.setFollowRedirects(false);
int status = httpClient.executeMethod(method);
redirectCount = 0;
while (redirectCount++ < 10 && method.getStatusCode() == 302) {
method.releaseConnection();
method = new GetMethod(method.getResponseHeader("Location").getValue());
method.setFollowRedirects(false);
status = httpClient.executeMethod(method);
}
if (method.getStatusCode() == 302) {
throw new IOException("Maximum redirections reached");
}
if (status != HttpStatus.SC_OK) {
HttpException ex = new HttpException();
ex.setReasonCode(status);

View File

@ -0,0 +1,98 @@
package davmail.exchange;
import davmail.Settings;
import davmail.http.DavGatewayHttpClientFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import java.io.IOException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
/**
* Create ExchangeSession instances.
*/
public class ExchangeSessionFactory {
/**
* Create authenticated Exchange session
*
* @param userName user login
* @param password user password
* @return authenticated session
* @throws java.io.IOException on error
*/
public static ExchangeSession getInstance(String userName, String password) throws IOException {
try {
ExchangeSession session = new ExchangeSession();
session.login(userName, password);
return session;
} catch (IOException e) {
if (checkNetwork()) {
throw e;
} else {
throw new IOException("All network interfaces down !");
}
}
}
public static void checkConfig() throws IOException {
try {
String url = Settings.getProperty("davmail.url");
// create an HttpClient instance
HttpClient httpClient = DavGatewayHttpClientFactory.getInstance();
// get webmail root url (will not follow redirects)
HttpMethod testMethod = new GetMethod(url);
testMethod.setFollowRedirects(false);
int status = httpClient.executeMethod(testMethod);
testMethod.releaseConnection();
ExchangeSession.LOGGER.debug("Test configuration status: " + status);
if (status != HttpStatus.SC_OK && status != HttpStatus.SC_UNAUTHORIZED
&& status != HttpStatus.SC_MOVED_TEMPORARILY) {
throw new IOException("Unable to connect to OWA at " + url + ", status code " +
status + ", check configuration");
}
} catch (UnknownHostException exc) {
String message = "DavMail configuration exception: \n Unknown host ";
if (checkNetwork()) {
message += exc.getMessage();
} else {
message += "All network interfaces down !";
}
ExchangeSession.LOGGER.error(message, exc);
throw new IOException(message, exc);
} catch (Exception exc) {
ExchangeSession.LOGGER.error("DavMail configuration exception: \n" + exc.getMessage(), exc);
throw new IOException("DavMail configuration exception: \n" + exc.getMessage(), exc);
}
}
/**
* Check if at least one network interface is up and active (i.e. has an address)
* @return true if network available
*/
protected static boolean checkNetwork() {
boolean up = false;
Enumeration<NetworkInterface> enumeration;
try {
enumeration = NetworkInterface.getNetworkInterfaces();
while (!up && enumeration.hasMoreElements()) {
NetworkInterface networkInterface = enumeration.nextElement();
up = networkInterface.isUp() && !networkInterface.isLoopback()
&& networkInterface.getInetAddresses().hasMoreElements();
}
} catch (SocketException exc) {
ExchangeSession.LOGGER.error("DavMail configuration exception: \n Error listing network interfaces " + exc.getMessage(), exc);
}
return up;
}
}

View File

@ -0,0 +1,72 @@
package davmail.http;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import davmail.Settings;
/**
* Create HttpClient instance according to DavGateway Settings
*/
public class DavGatewayHttpClientFactory {
/**
* Create a configured HttpClient instance.
*
* @return httpClient
*/
public static HttpClient getInstance() {
// create an HttpClient instance
HttpClient httpClient = new HttpClient();
configureClient(httpClient);
return httpClient;
}
/**
* Update http client configuration (proxy)
*
* @param httpClient current Http client
*/
public static void configureClient(HttpClient httpClient) {
// do not send basic auth automatically
httpClient.getState().setAuthenticationPreemptive(false);
boolean enableProxy = Settings.getBooleanProperty("davmail.enableProxy");
String proxyHost = null;
int proxyPort = 0;
String proxyUser = null;
String proxyPassword = null;
if (enableProxy) {
proxyHost = Settings.getProperty("davmail.proxyHost");
proxyPort = Settings.getIntProperty("davmail.proxyPort");
proxyUser = Settings.getProperty("davmail.proxyUser");
proxyPassword = Settings.getProperty("davmail.proxyPassword");
}
// configure proxy
if (proxyHost != null && proxyHost.length() > 0) {
httpClient.getHostConfiguration().setProxy(proxyHost, proxyPort);
if (proxyUser != null && proxyUser.length() > 0) {
/* // Only available in newer HttpClient releases, not compatible with slide library
List authPrefs = new ArrayList();
authPrefs.add(AuthPolicy.BASIC);
httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY,authPrefs);
*/
// instead detect ntlm authentication (windows domain name in user name)
int backslashindex = proxyUser.indexOf("\\");
if (backslashindex > 0) {
httpClient.getState().setProxyCredentials(null, proxyHost,
new NTCredentials(proxyUser.substring(backslashindex + 1),
proxyPassword, null,
proxyUser.substring(0, backslashindex)));
} else {
httpClient.getState().setProxyCredentials(null, proxyHost,
new UsernamePasswordCredentials(proxyUser, proxyPassword));
}
}
}
}
}

View File

@ -0,0 +1,111 @@
package davmail.http;
import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.Protocol;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.net.MalformedURLException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import davmail.Settings;
import davmail.tray.DavGatewayTray;
/**
* Manual Socket Factory.
* Let user choose to accept or reject certificate
*/
public class DavGatewaySSLProtocolSocketFactory extends SSLProtocolSocketFactory {
/**
* Register custom Socket Factory to let user accept or reject certificate
*/
public static void register() {
String urlString = Settings.getProperty("davmail.url");
try {
URL url = new URL(urlString);
String protocol = url.getProtocol();
if ("https".equals(protocol)) {
int port = url.getPort();
if (port < 0) {
port = 443;
}
Protocol.registerProtocol(url.getProtocol(),
new Protocol(protocol, new DavGatewaySSLProtocolSocketFactory(), port));
}
} catch (MalformedURLException e) {
DavGatewayTray.error("Exception handling url: " + urlString);
}
}
private SSLContext sslcontext = null;
private SSLContext createSSLContext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
SSLContext context = SSLContext.getInstance("SSL");
context.init(
null,
new TrustManager[]{new DavGatewayX509TrustManager()},
null);
return context;
}
private SSLContext getSSLContext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
if (this.sslcontext == null) {
this.sslcontext = createSSLContext();
}
return this.sslcontext;
}
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException {
try {
return getSSLContext().getSocketFactory().createSocket(
host,
port,
clientHost,
clientPort
);
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
} catch (KeyManagementException e) {
throw new IOException(e);
} catch (KeyStoreException e) {
throw new IOException(e);
}
}
public Socket createSocket(String host, int port) throws IOException {
try {
return getSSLContext().getSocketFactory().createSocket(
host,
port
);
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
} catch (KeyManagementException e) {
throw new IOException(e);
} catch (KeyStoreException e) {
throw new IOException(e);
}
}
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
try {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose
);
} catch (NoSuchAlgorithmException e) {
throw new IOException(e);
} catch (KeyManagementException e) {
throw new IOException(e);
} catch (KeyStoreException e) {
throw new IOException(e);
}
}
}

View File

@ -8,6 +8,7 @@ import java.io.IOException;
import davmail.AbstractConnection;
import davmail.tray.DavGatewayTray;
import davmail.exchange.ExchangeSession;
import davmail.exchange.ExchangeSessionFactory;
/**
* Dav Gateway smtp connection implementation.
@ -50,9 +51,8 @@ public class ImapConnection extends AbstractConnection {
sendClient(commandId + " OK CAPABILITY completed");
} else if ("login".equalsIgnoreCase(command)) {
parseCredentials(tokens);
session = new ExchangeSession();
try {
session.login(userName, password);
session = ExchangeSessionFactory.getInstance(userName, password);
sendClient(commandId + " OK Authenticated");
state = AUTHENTICATED;
} catch (Exception e) {
@ -127,7 +127,7 @@ public class ImapConnection extends AbstractConnection {
os.flush();
} catch (IOException e) {
DavGatewayTray.error("Exception handling client",e);
DavGatewayTray.error("Exception handling client", e);
} finally {
close();
}

View File

@ -2,6 +2,7 @@ package davmail.pop;
import davmail.AbstractConnection;
import davmail.exchange.ExchangeSession;
import davmail.exchange.ExchangeSessionFactory;
import davmail.tray.DavGatewayTray;
import java.io.FilterOutputStream;
@ -64,7 +65,7 @@ public class PopConnection extends AbstractConnection {
StringTokenizer tokens;
try {
ExchangeSession.checkConfig();
ExchangeSessionFactory.checkConfig();
sendOK("DavMail POP ready at " + new Date());
for (; ;) {
@ -107,8 +108,7 @@ public class PopConnection extends AbstractConnection {
} else {
password = tokens.nextToken();
try {
session = new ExchangeSession();
session.login(userName, password);
session = ExchangeSessionFactory.getInstance(userName, password);
messages = session.getAllMessages();
sendOK("PASS");
state = AUTHENTICATED;

View File

@ -1,8 +1,8 @@
package davmail.smtp;
import davmail.AbstractConnection;
import davmail.exchange.ExchangeSessionFactory;
import davmail.tray.DavGatewayTray;
import davmail.exchange.ExchangeSession;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
@ -33,7 +33,7 @@ public class SmtpConnection extends AbstractConnection {
StringTokenizer tokens;
try {
ExchangeSession.checkConfig();
ExchangeSessionFactory.checkConfig();
sendClient("220 DavMail SMTP ready at " + new Date());
for (; ;) {
line = readClient();
@ -142,9 +142,8 @@ public class SmtpConnection extends AbstractConnection {
* @throws IOException on error
*/
protected void authenticate() throws IOException {
session = new ExchangeSession();
try {
session.login(userName, password);
session = ExchangeSessionFactory.getInstance(userName, password);
sendClient("235 OK Authenticated");
state = AUTHENTICATED;
} catch (Exception e) {

View File

@ -102,6 +102,7 @@ public class AwtGatewayTray implements DavGatewayTrayInterface {
// create an action settingsListener to listen for settings action executed on the tray icon
ActionListener settingsListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
settingsFrame.reload();
settingsFrame.setVisible(true);
}
};

View File

@ -16,7 +16,7 @@ public class DavGatewayTray {
protected DavGatewayTray() {
}
protected static DavGatewayTrayInterface davGatewayTray;
static DavGatewayTrayInterface davGatewayTray;
public static void switchIcon() {
if (davGatewayTray != null) {
@ -40,7 +40,7 @@ public class DavGatewayTray {
protected static void displayMessage(String message, Exception e, Priority priority) {
LOGGER.log(priority, message, e);
if (davGatewayTray != null) {
davGatewayTray.displayMessage(message + " " + e +" "+ e.getMessage(), priority);
davGatewayTray.displayMessage(message + " " + e + " " + e.getMessage(), priority);
}
}

View File

@ -177,6 +177,7 @@ public class SwtGatewayTray implements DavGatewayTrayInterface {
display.asyncExec(
new Runnable() {
public void run() {
settingsFrame.reload();
settingsFrame.setVisible(true);
}
});
@ -191,6 +192,7 @@ public class SwtGatewayTray implements DavGatewayTrayInterface {
display.asyncExec(
new Runnable() {
public void run() {
settingsFrame.reload();
settingsFrame.setVisible(true);
}
});

View File

@ -0,0 +1,143 @@
package davmail.ui;
import davmail.http.DavGatewayX509TrustManager;
import davmail.tray.DavGatewayTray;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
/**
* Accept certificate dialog
*/
public class AcceptCertificateDialog extends JDialog {
protected boolean accepted;
public boolean isAccepted() {
return accepted;
}
public void addFieldValue(JPanel panel, String label, String value) {
JPanel fieldPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
StringBuilder buffer = new StringBuilder();
buffer.append("<html><b>");
buffer.append(label);
buffer.append(":</b></html>");
fieldPanel.add(new JLabel(buffer.toString()));
fieldPanel.add(new JLabel(value));
panel.add(fieldPanel);
}
protected String getRDN(Principal principal) {
String dn = principal.getName();
int start = dn.indexOf('=');
int end = dn.indexOf(',');
if (start >= 0 && end >= 0) {
return dn.substring(start + 1, end);
} else {
return dn;
}
}
public String getFormattedSerial(X509Certificate certificate) {
StringBuilder builder = new StringBuilder();
String serial = certificate.getSerialNumber().toString(16);
for (int i = 0;i<serial.length();i++) {
if (i > 0 && i%2 == 0) {
builder.append(' ');
}
builder.append(serial.charAt(i));
}
return builder.toString();
}
public AcceptCertificateDialog(X509Certificate certificate) {
String sha1Hash;
try {
sha1Hash = DavGatewayX509TrustManager.getFormattedHash(certificate);
} catch (NoSuchAlgorithmException nsa) {
sha1Hash = nsa.getMessage();
} catch (CertificateEncodingException cee) {
sha1Hash = cee.getMessage();
}
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
setTitle("Accept certificate ?");
JPanel subjectPanel = new JPanel();
subjectPanel.setLayout(new BoxLayout(subjectPanel, BoxLayout.Y_AXIS));
subjectPanel.setBorder(BorderFactory.createTitledBorder("Server Certificate"));
addFieldValue(subjectPanel, "Issued to", getRDN(certificate.getSubjectDN()));
addFieldValue(subjectPanel, "Issued by", getRDN(certificate.getIssuerDN()));
addFieldValue(subjectPanel, "Valid from", formatter.format(certificate.getNotBefore()));
addFieldValue(subjectPanel, "Valid until", formatter.format(certificate.getNotAfter()));
addFieldValue(subjectPanel, "Serial", getFormattedSerial(certificate));
addFieldValue(subjectPanel, "FingerPrint", sha1Hash);
JPanel warningPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel imageLabel = new JLabel();
imageLabel.setIcon(UIManager.getIcon("OptionPane.warningIcon"));
imageLabel.setText("<html><b>Server provided an untrusted certificate,<br> you can choose to accept or deny access</b></html>");
warningPanel.add(imageLabel);
add(warningPanel, BorderLayout.NORTH);
add(subjectPanel, BorderLayout.CENTER);
add(getButtonPanel(), BorderLayout.SOUTH);
setModal(true);
pack();
// center frame
setLocation(getToolkit().getScreenSize().width / 2 -
getSize().width / 2,
getToolkit().getScreenSize().height / 2 -
getSize().height / 2);
setVisible(true);
}
protected JPanel getButtonPanel() {
JPanel buttonPanel = new JPanel();
JButton accept = new JButton("Accept");
JButton deny = new JButton("Deny");
accept.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
accepted = true;
dispose();
}
});
deny.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
accepted = false;
dispose();
}
});
buttonPanel.add(accept);
buttonPanel.add(deny);
return buttonPanel;
}
public static boolean isCertificateTrusted(final X509Certificate certificate) {
final boolean[] answer = new boolean[1];
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
AcceptCertificateDialog certificateDialog = new AcceptCertificateDialog(certificate);
answer[0] = certificateDialog.isAccepted();
}
});
} catch (InterruptedException ie) {
DavGatewayTray.error("Error waiting for certificate check", ie);
} catch (InvocationTargetException ite) {
DavGatewayTray.error("Error waiting for certificate check", ite);
}
return answer[0];
}
}

View File

@ -19,7 +19,7 @@ public class TestExchangeSession {
ExchangeSession session = new ExchangeSession();
// test auth
try {
ExchangeSession.checkConfig();
ExchangeSessionFactory.checkConfig();
session.login(argv[currentArg++], argv[currentArg++]);
ExchangeSession.Folder folder = session.selectFolder(argv[currentArg++]);