Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorspingel2008-10-13 08:36:36 +0000
committerspingel2008-10-13 08:36:36 +0000
commitf543f0985301bbe1831a089a45a4bfcea4e65ff7 (patch)
treea29a14cabfd29d3a0addb81c018551c71cf1c036 /org.eclipse.mylyn.trac.core
parentd2b8cfa3e734b46ae99750bb0335b1d1cc5e05cf (diff)
downloadorg.eclipse.mylyn.tasks-f543f0985301bbe1831a089a45a4bfcea4e65ff7.tar.gz
org.eclipse.mylyn.tasks-f543f0985301bbe1831a089a45a4bfcea4e65ff7.tar.xz
org.eclipse.mylyn.tasks-f543f0985301bbe1831a089a45a4bfcea4e65ff7.zip
NEW - bug 214341: Large XML-RPC requests fail when using digest authentication and tracd
https://bugs.eclipse.org/bugs/show_bug.cgi?id=214341
Diffstat (limited to 'org.eclipse.mylyn.trac.core')
-rw-r--r--org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java9
-rw-r--r--org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java90
-rw-r--r--org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/HttpRequestInterceptor.java23
-rw-r--r--org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracHttpClientTransportFactory.java59
4 files changed, 131 insertions, 50 deletions
diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java
index faeffe1e0..c60f4e56c 100644
--- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java
+++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracWebClient.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2006, 2008 Steffen Pingel and others.
+ * Copyright (c) 2006, 2008 Steffen Pingel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -126,8 +126,9 @@ public class TracWebClient extends AbstractTracClient {
throw new TracLoginException();
}
- // try standard basic/digest authentication first
- AuthScope authScope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);
+ // try standard basic/digest/ntlm authentication first
+ AuthScope authScope = new AuthScope(WebUtil.getHost(repositoryUrl), WebUtil.getPort(repositoryUrl),
+ null, AuthScope.ANY_SCHEME);
httpClient.getState().setCredentials(authScope,
WebUtil.getHttpClientCredentials(credentials, WebUtil.getHost(repositoryUrl)));
@@ -135,14 +136,12 @@ public class TracWebClient extends AbstractTracClient {
method.setFollowRedirects(false);
int code;
try {
- httpClient.getParams().setAuthenticationPreemptive(true);
code = WebUtil.execute(httpClient, hostConfiguration, method, monitor);
if (needsReauthentication(code, monitor)) {
continue;
}
} finally {
method.releaseConnection();
- httpClient.getParams().setAuthenticationPreemptive(false);
}
// the expected return code is a redirect, anything else is suspicious
diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java
index 01b1e2afd..68f9e96de 100644
--- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java
+++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/client/TracXmlRpcClient.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2006, 2008 Steffen Pingel and others.
+ * Copyright (c) 2006, 2008 Steffen Pingel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,9 +27,18 @@ import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.auth.AuthenticationException;
+import org.apache.commons.httpclient.auth.DigestScheme;
+import org.apache.commons.httpclient.auth.MalformedChallengeException;
+import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
@@ -62,6 +71,7 @@ import org.eclipse.mylyn.internal.trac.core.model.TracVersion;
import org.eclipse.mylyn.internal.trac.core.model.TracWikiPage;
import org.eclipse.mylyn.internal.trac.core.model.TracWikiPageInfo;
import org.eclipse.mylyn.internal.trac.core.model.TracTicket.Key;
+import org.eclipse.mylyn.internal.trac.core.util.HttpRequestInterceptor;
import org.eclipse.mylyn.internal.trac.core.util.TracHttpClientTransportFactory;
import org.eclipse.mylyn.internal.trac.core.util.TracUtil;
import org.eclipse.mylyn.internal.trac.core.util.TracXmlRpcClientRequest;
@@ -124,7 +134,7 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli
throw e;
}
- factory.setCookies(httpClient.getState().getCookies());
+ // the authentication information is available through the shared state in httpClient
}
// second attempt
@@ -138,8 +148,10 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli
return xmlrpc.execute(request);
} catch (TracHttpException e) {
if (e.code == HttpStatus.SC_UNAUTHORIZED) {
+ digestScheme = null;
throw new TracLoginException();
} else if (e.code == HttpStatus.SC_FORBIDDEN) {
+ digestScheme = null;
throw new TracPermissionDeniedException();
} else if (e.code == HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED) {
throw new TracProxyAuthenticationException();
@@ -193,9 +205,17 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli
private final HttpClient httpClient;
+ private boolean probed;
+
+ private volatile DigestScheme digestScheme;
+
+ private final AuthScope authScope;
+
public TracXmlRpcClient(AbstractWebLocation location, Version version) {
super(location, version);
this.httpClient = createHttpClient();
+ this.authScope = new AuthScope(WebUtil.getHost(repositoryUrl), WebUtil.getPort(repositoryUrl), null,
+ AuthScope.ANY_SCHEME);
}
public synchronized XmlRpcClient getClient() throws TracException {
@@ -212,19 +232,33 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli
factory = new TracHttpClientTransportFactory(xmlrpc, httpClient);
factory.setLocation(location);
+ factory.setInterceptor(new HttpRequestInterceptor() {
+ public void process(HttpMethod method) {
+ DigestScheme scheme = digestScheme;
+ if (scheme != null) {
+ Credentials creds = httpClient.getState().getCredentials(authScope);
+ if (creds != null) {
+ try {
+ method.addRequestHeader("Authorization", scheme.authenticate(creds, method));
+ } catch (AuthenticationException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ });
xmlrpc.setTransportFactory(factory);
}
// update configuration with latest values
AuthenticationCredentials credentials = location.getCredentials(AuthenticationType.REPOSITORY);
+ config.setServerURL(getXmlRpcUrl(credentials));
if (credentialsValid(credentials)) {
- config.setBasicUserName(credentials.getUserName());
- config.setBasicPassword(credentials.getPassword());
+ Credentials creds = new UsernamePasswordCredentials(credentials.getUserName(), credentials.getPassword());
+ httpClient.getState().setCredentials(authScope, creds);
} else {
- config.setBasicUserName(null);
- config.setBasicPassword(null);
+ httpClient.getState().clearCredentials();
}
- config.setServerURL(getXmlRpcUrl(credentials));
return xmlrpc;
}
@@ -243,9 +277,51 @@ public class TracXmlRpcClient extends AbstractTracClient implements ITracWikiCli
}
}
+ private void probeAuthenticationScheme(IProgressMonitor monitor) throws TracException {
+ if (probed) {
+ return;
+ }
+
+ try {
+ AuthenticationCredentials credentials = location.getCredentials(AuthenticationType.REPOSITORY);
+ if (!credentialsValid(credentials)) {
+ return;
+ }
+
+ HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(httpClient, location, monitor);
+ HeadMethod method = new HeadMethod(getXmlRpcUrl(credentials).toString());
+ try {
+ int result = WebUtil.execute(httpClient, hostConfiguration, method, monitor);
+ if (result == HttpStatus.SC_UNAUTHORIZED || result == HttpStatus.SC_FORBIDDEN) {
+ Header header = method.getResponseHeader("WWW-Authenticate");
+ if (header != null) {
+ if (header.getValue().startsWith("Basic")) {
+ httpClient.getParams().setAuthenticationPreemptive(true);
+ } else if (header.getValue().startsWith("Digest")) {
+ DigestScheme scheme = new DigestScheme();
+ try {
+ scheme.processChallenge(header.getValue());
+ this.digestScheme = scheme;
+ } catch (MalformedChallengeException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ // ignore
+ } finally {
+ method.releaseConnection();
+ }
+ } finally {
+ probed = true;
+ }
+ }
+
private Object call(IProgressMonitor monitor, String method, Object... parameters) throws TracException {
monitor = Policy.monitorFor(monitor);
while (true) {
+ probeAuthenticationScheme(monitor);
getClient();
try {
diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/HttpRequestInterceptor.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/HttpRequestInterceptor.java
new file mode 100644
index 000000000..bc2938a8d
--- /dev/null
+++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/HttpRequestInterceptor.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.trac.core.util;
+
+import org.apache.commons.httpclient.HttpMethod;
+
+/**
+ * @author Steffen Pingel
+ */
+public interface HttpRequestInterceptor {
+
+ public abstract void process(HttpMethod method);
+
+}
diff --git a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracHttpClientTransportFactory.java b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracHttpClientTransportFactory.java
index 94f787caa..1033f7ec2 100644
--- a/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracHttpClientTransportFactory.java
+++ b/org.eclipse.mylyn.trac.core/src/org/eclipse/mylyn/internal/trac/core/util/TracHttpClientTransportFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
-* Copyright (c) 2006, 2008 Steffen Pingel and others.
+ * Copyright (c) 2006, 2008 Steffen Pingel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,18 +18,13 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
-import org.apache.commons.httpclient.Cookie;
-import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpVersion;
-import org.apache.commons.httpclient.UsernamePasswordCredentials;
-import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
-import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.client.XmlRpcClient;
@@ -38,7 +33,6 @@ import org.apache.xmlrpc.client.XmlRpcHttpClientConfig;
import org.apache.xmlrpc.client.XmlRpcHttpTransport;
import org.apache.xmlrpc.client.XmlRpcTransport;
import org.apache.xmlrpc.client.XmlRpcTransportFactory;
-import org.apache.xmlrpc.common.XmlRpcStreamConfig;
import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
import org.apache.xmlrpc.util.HttpUtil;
import org.apache.xmlrpc.util.XmlRpcIOException;
@@ -63,8 +57,6 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
private final AbstractWebLocation location;
- private final Cookie[] cookies;
-
private PostMethod method;
private int contentLength = -1;
@@ -75,13 +67,14 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
private HostConfiguration hostConfiguration;
+ private final HttpRequestInterceptor interceptor;
+
public TracHttpClientTransport(XmlRpcClient client, HttpClient httpClient, AbstractWebLocation location,
- Cookie[] cookies) {
+ HttpRequestInterceptor interceptor) {
super(client, "");
-
this.httpClient = httpClient;
this.location = location;
- this.cookies = cookies;
+ this.interceptor = interceptor;
}
@Override
@@ -127,9 +120,6 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
String url = config.getServerURL().toString();
hostConfiguration = WebUtil.createHostConfiguration(httpClient, location, monitor);
- if (cookies != null) {
- httpClient.getState().addCookies(cookies);
- }
method = new PostMethod(WebUtil.getRequestPath(url));
super.initHttpHeaders(request);
@@ -143,6 +133,10 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
}
method.getParams().setVersion(HttpVersion.HTTP_1_1);
+
+ if (interceptor != null) {
+ interceptor.process(method);
+ }
}
@Override
@@ -158,18 +152,7 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
@Override
protected void setCredentials(XmlRpcHttpClientConfig config) throws XmlRpcClientException {
- String userName = config.getBasicUserName();
- if (userName != null) {
- String encoding = config.getBasicEncoding();
- if (encoding == null) {
- encoding = XmlRpcStreamConfig.UTF8_ENCODING;
- }
- httpClient.getParams().setParameter(HttpMethodParams.CREDENTIAL_CHARSET, encoding);
- Credentials creds = new UsernamePasswordCredentials(userName, config.getBasicPassword());
- AuthScope scope = new AuthScope(null, AuthScope.ANY_PORT, null, AuthScope.ANY_SCHEME);
- httpClient.getState().setCredentials(scope, creds);
- httpClient.getParams().setAuthenticationPreemptive(true);
- }
+ // handled by TracXmlRpcClient
}
@Override
@@ -253,35 +236,35 @@ public class TracHttpClientTransportFactory implements XmlRpcTransportFactory {
private final XmlRpcClient xmlRpcClient;
- private Cookie[] cookies;
-
private AbstractWebLocation location;
private final HttpClient httpClient;
+ private HttpRequestInterceptor interceptor;
+
public TracHttpClientTransportFactory(XmlRpcClient xmlRpcClient, HttpClient httpClient) {
this.xmlRpcClient = xmlRpcClient;
this.httpClient = httpClient;
}
- public Cookie[] getCookies() {
- return cookies;
- }
-
public AbstractWebLocation getLocation() {
return location;
}
public XmlRpcTransport getTransport() {
- return new TracHttpClientTransport(xmlRpcClient, httpClient, location, cookies);
- }
-
- public void setCookies(Cookie[] cookies) {
- this.cookies = cookies;
+ return new TracHttpClientTransport(xmlRpcClient, httpClient, location, interceptor);
}
public void setLocation(AbstractWebLocation location) {
this.location = location;
}
+ public HttpRequestInterceptor getInterceptor() {
+ return interceptor;
+ }
+
+ public void setInterceptor(HttpRequestInterceptor interceptor) {
+ this.interceptor = interceptor;
+ }
+
}

Back to the top