diff --git a/src/java/davmail/exchange/ExchangeSession.java b/src/java/davmail/exchange/ExchangeSession.java index c6a6803d..7db9a757 100644 --- a/src/java/davmail/exchange/ExchangeSession.java +++ b/src/java/davmail/exchange/ExchangeSession.java @@ -227,8 +227,10 @@ public class ExchangeSession { method = formLogin(httpClient, method, userName, password); } - // avoid 401 roundtrips - httpClient.getParams().setParameter(HttpClientParams.PREEMPTIVE_AUTHENTICATION, true); + // avoid 401 roundtrips, only if NTLM is disabled + if (!DavGatewayHttpClientFacade.hasNTLM(httpClient)) { + httpClient.getParams().setParameter(HttpClientParams.PREEMPTIVE_AUTHENTICATION, true); + } buildMailPath(method); diff --git a/src/java/davmail/exchange/ExchangeSessionFactory.java b/src/java/davmail/exchange/ExchangeSessionFactory.java index de5781d8..bb10e106 100644 --- a/src/java/davmail/exchange/ExchangeSessionFactory.java +++ b/src/java/davmail/exchange/ExchangeSessionFactory.java @@ -20,16 +20,16 @@ package davmail.exchange; import davmail.BundleMessage; import davmail.Settings; -import davmail.exception.DavMailException; import davmail.exception.DavMailAuthenticationException; +import davmail.exception.DavMailException; import davmail.http.DavGatewayHttpClientFacade; 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.*; +import java.net.NetworkInterface; +import java.net.SocketException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -124,6 +124,8 @@ public final class ExchangeSessionFactory { throw exc; } catch (DavMailException exc) { throw exc; + } catch (IllegalStateException exc) { + throw exc; } catch (Exception exc) { handleNetworkDown(exc); } @@ -172,12 +174,11 @@ public final class ExchangeSessionFactory { public static void checkConfig() throws IOException { String url = Settings.getProperty("davmail.url"); HttpClient httpClient = DavGatewayHttpClientFacade.getInstance(); - HttpMethod testMethod = new GetMethod(url); + GetMethod testMethod = new GetMethod(url); try { // get webMail root url (will not follow redirects) - testMethod.setFollowRedirects(false); testMethod.setDoAuthentication(false); - int status = httpClient.executeMethod(testMethod); + int status = DavGatewayHttpClientFacade.executeGetMethod(httpClient, testMethod, false); ExchangeSession.LOGGER.debug("Test configuration status: " + status); if (status != HttpStatus.SC_OK && status != HttpStatus.SC_UNAUTHORIZED && status != HttpStatus.SC_MOVED_TEMPORARILY && status != HttpStatus.SC_MOVED_PERMANENTLY) { diff --git a/src/java/davmail/http/DavGatewayHttpClientFacade.java b/src/java/davmail/http/DavGatewayHttpClientFacade.java index 2bbc5a07..af4ddb91 100644 --- a/src/java/davmail/http/DavGatewayHttpClientFacade.java +++ b/src/java/davmail/http/DavGatewayHttpClientFacade.java @@ -363,7 +363,12 @@ public final class DavGatewayHttpClientFacade { return status; } - private static boolean hasNTLM(HttpClient httpClient) { + /** + * Test if NTLM auth scheme is enabled. + * @param httpClient HttpClient instance + * @return true if NTLM is enabled + */ + public static boolean hasNTLM(HttpClient httpClient) { Object authPrefs = httpClient.getParams().getParameter(AuthPolicy.AUTH_SCHEME_PRIORITY); return authPrefs instanceof List && ((Collection) authPrefs).contains(AuthPolicy.NTLM); } @@ -376,6 +381,19 @@ public final class DavGatewayHttpClientFacade { httpClient.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs); } + private static boolean acceptsNTLMOnly(GetMethod getMethod) { + Header authenticateHeader = null; + if (getMethod.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + authenticateHeader = getMethod.getResponseHeader("Authenticate"); + } else if (getMethod.getStatusCode() == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) { + authenticateHeader = getMethod.getResponseHeader("Proxy-Authenticate"); + } + // check authenticate header + return (authenticateHeader != null) + && (authenticateHeader.getElements().length == 1) + && ("NTLM".equals(authenticateHeader.getElements()[0].getName())); + } + /** * Execute Get method, do not follow redirects. * @@ -383,18 +401,20 @@ public final class DavGatewayHttpClientFacade { * @param method Http method * @param followRedirects Follow redirects flag * @throws IOException on error + * @return Http status */ - public static void executeGetMethod(HttpClient httpClient, GetMethod method, boolean followRedirects) throws IOException { + public static int executeGetMethod(HttpClient httpClient, GetMethod method, boolean followRedirects) throws IOException { // do not follow redirects in expired sessions method.setFollowRedirects(followRedirects); int status = httpClient.executeMethod(method); - if (status == HttpStatus.SC_UNAUTHORIZED && !hasNTLM(httpClient)) { + if ((status == HttpStatus.SC_UNAUTHORIZED || status == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) + && acceptsNTLMOnly(method) && !hasNTLM(httpClient)) { method.releaseConnection(); - LOGGER.debug("Received unauthorized at " + method.getURI() + ", retrying with NTLM"); + LOGGER.debug("Received "+status+" unauthorized at " + method.getURI() + ", retrying with NTLM"); addNTLM(httpClient); status = httpClient.executeMethod(method); } - if (status != HttpStatus.SC_OK) { + if (status != HttpStatus.SC_OK && (followRedirects || !isRedirect(status))) { LOGGER.warn("GET failed with status " + status + " at " + method.getURI() + ": " + method.getResponseBodyAsString()); throw DavGatewayHttpClientFacade.buildHttpException(method); } @@ -407,6 +427,7 @@ public final class DavGatewayHttpClientFacade { throw DavGatewayHttpClientFacade.buildHttpException(method); } } + return status; } private static void checkExpiredSession(String queryString) throws DavMailAuthenticationException {