Skip to content

Commit 0637151

Browse files
committed
Add timeout to gathering host certificates #567
1 parent b4a50b8 commit 0637151

File tree

12 files changed

+69
-16
lines changed

12 files changed

+69
-16
lines changed

bundles/org.eclipse.equinox.p2.core/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.equinox.p2.core;singleton:=true
5-
Bundle-Version: 2.12.200.qualifier
5+
Bundle-Version: 2.12.300.qualifier
66
Bundle-Activator: org.eclipse.equinox.internal.p2.core.Activator
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/p2/core/IProvisioningAgent.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,32 @@ default boolean getBooleanProperty(String key, boolean defaultValue) {
165165
return Boolean.parseBoolean(getProperty(key, Boolean.toString(defaultValue)));
166166
}
167167

168+
/**
169+
* Returns an agent bound property as an int, the default implementation
170+
* delegates to {@link IProvisioningAgent#getIntProperty(String, int)} with
171+
* <code>0</code> as the default.
172+
*
173+
* @since 2.12
174+
*/
175+
default int getIntProperty(String key) {
176+
return getIntProperty(key, 0);
177+
}
178+
179+
/**
180+
* Returns an agent bound property as an int, the default implementation
181+
* delegates to {@link IProvisioningAgent#getProperty(String)} with the given
182+
* default as a String and parses the result as by
183+
* {@link Boolean#parseBoolean(String)}.
184+
*
185+
* @since 2.12
186+
*/
187+
default int getIntProperty(String key, int defaultValue) {
188+
String propertyValue = getProperty(key, Integer.toString(defaultValue));
189+
try {
190+
return Integer.parseInt(propertyValue);
191+
} catch (NumberFormatException e) {
192+
return defaultValue;
193+
}
194+
}
195+
168196
}

bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.equinox.p2.engine;singleton:=true
5-
Bundle-Version: 2.10.300.qualifier
5+
Bundle-Version: 2.10.400.qualifier
66
Bundle-Activator: org.eclipse.equinox.internal.p2.engine.EngineActivator
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/Messages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class Messages extends NLS {
2525
public static String ActionManager_Required_Touchpoint_Not_Found;
2626

2727
public static String AuthorityChecker_UntrustedAuthorities;
28+
public static String AuthorityChecker_GatherCertificatesFailure;
2829

2930
public static String actions_not_found;
3031
private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.engine.messages"; //$NON-NLS-1$

bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
ActionManager_Exception_Creating_Action_Extension=Error creating action with id: {0}.
1616
ActionManager_Required_Touchpoint_Not_Found=The required {0} touchpoint for the {1} action is not included in the installation manager configuration.
1717
AuthorityChecker_UntrustedAuthorities=One or more authorities is not trusted. Cannot proceed with installation.
18+
AuthorityChecker_GatherCertificatesFailure=Obtaining a host certificate resulted in an exception. This host will be ignored.
1819
action_syntax_error=Invalid action syntax: {0}.
1920
download_artifact=Downloading artifacts
2021
download_no_repository=No artifact repository available.

bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/AuthorityChecker.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.net.http.HttpRequest.BodyPublishers;
1717
import java.net.http.HttpResponse.BodyHandlers;
1818
import java.security.cert.Certificate;
19+
import java.time.Duration;
1920
import java.util.*;
2021
import java.util.concurrent.CompletableFuture;
2122
import java.util.concurrent.ExecutionException;
@@ -25,6 +26,7 @@
2526
import javax.net.ssl.SSLPeerUnverifiedException;
2627
import org.eclipse.core.runtime.*;
2728
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
29+
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
2830
import org.eclipse.equinox.internal.p2.engine.EngineActivator;
2931
import org.eclipse.equinox.internal.p2.engine.Messages;
3032
import org.eclipse.equinox.p2.core.*;
@@ -52,6 +54,10 @@ public class AuthorityChecker {
5254
private static final Pattern HIERARCHICAL_URI_PATTERN = Pattern
5355
.compile("((?:[^/:]+):(?://[^/]+|///|/)?)([^?#]*)([#?].*)?"); //$NON-NLS-1$
5456

57+
private final int requestTimeoutMillis;
58+
59+
private final int maxRequestRetries;
60+
5561
private final IProvisioningAgent agent;
5662
private final ProvisioningContext context;
5763
private final IProfile profile;
@@ -75,6 +81,9 @@ public AuthorityChecker(IProvisioningAgent agent, IProfile profile) {
7581
this.ius = ius;
7682
this.artifacts = artifacts;
7783
this.profile = profile;
84+
requestTimeoutMillis = agent.getIntProperty("org.eclipse.equinox.p2.engine.certificateRequestTimeout", 5000);//$NON-NLS-1$
85+
maxRequestRetries = agent.getIntProperty("org.eclipse.equinox.p2.engine.certificateRequestRetries", //$NON-NLS-1$
86+
3);
7887
}
7988

8089
IStatus start(IProgressMonitor monitor) {
@@ -235,7 +244,7 @@ public static List<URI> getFilteredAuthorities(Collection<? extends URI> authori
235244
return filteredAuthorities;
236245
}
237246

238-
public static Map<URI, List<Certificate>> getCertificates(Collection<? extends URI> uris,
247+
public Map<URI, List<Certificate>> getCertificates(Collection<? extends URI> uris,
239248
IProgressMonitor monitor) {
240249
var certificates = new TreeMap<URI, List<Certificate>>();
241250
var authorities = new TreeMap<URI, List<Certificate>>();
@@ -247,13 +256,14 @@ public static Map<URI, List<Certificate>> getCertificates(Collection<? extends U
247256
return certificates;
248257
}
249258

250-
public static void gatherCertificates(Map<URI, List<Certificate>> authorities, IProgressMonitor montior) {
259+
public void gatherCertificates(Map<URI, List<Certificate>> authorities, IProgressMonitor montior) {
251260
var client = HttpClient.newBuilder().build();
252261
var requests = authorities.keySet().stream().collect(Collectors.toMap(Function.identity(), uri -> {
253262
try {
254-
return Optional.of(client.sendAsync(
255-
HttpRequest.newBuilder().uri(uri).method("HEAD", BodyPublishers.noBody()).build(), //$NON-NLS-1$
256-
BodyHandlers.ofString()));
263+
var request = HttpRequest.newBuilder().uri(uri).timeout(Duration.ofMillis(requestTimeoutMillis))
264+
.method("HEAD", BodyPublishers.noBody()) //$NON-NLS-1$
265+
.build();
266+
return Optional.of(sendHttpRequestOrRetry(client, request, maxRequestRetries));
257267
} catch (RuntimeException ex) {
258268
return Optional.<CompletableFuture<HttpResponse<String>>>ofNullable(null);
259269
}
@@ -270,16 +280,29 @@ public static void gatherCertificates(Map<URI, List<Certificate>> authorities, I
270280
var peerCertificates = sslSession.getPeerCertificates();
271281
entry.getValue().addAll(Arrays.asList(peerCertificates));
272282
} catch (SSLPeerUnverifiedException e) {
273-
//$FALL-THROUGH$
283+
LogHelper.log(new Status(IStatus.WARNING, EngineActivator.ID,
284+
Messages.AuthorityChecker_GatherCertificatesFailure, e));
274285
}
275286
});
276-
} catch (RuntimeException | InterruptedException | ExecutionException e) {
277-
//$FALL-THROUGH$
287+
} catch (InterruptedException e) {
288+
Thread.currentThread().interrupt();
289+
} catch (RuntimeException | ExecutionException e) {
290+
LogHelper.log(new Status(IStatus.WARNING, EngineActivator.ID,
291+
Messages.AuthorityChecker_GatherCertificatesFailure, e));
278292
}
279293
});
280294
}
281295
}
282296

297+
private static CompletableFuture<HttpResponse<String>> sendHttpRequestOrRetry(HttpClient client,
298+
HttpRequest request, int retriesLeft) {
299+
var future = client.sendAsync(request, BodyHandlers.ofString());
300+
if (retriesLeft > 1) {
301+
future = future.exceptionallyComposeAsync(e -> sendHttpRequestOrRetry(client, request, retriesLeft - 1));
302+
}
303+
return future;
304+
}
305+
283306
/**
284307
* <p>
285308
* Returns a list of URIs representing the hierarchical chain, starting from the

bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %bundleName
44
Bundle-SymbolicName: org.eclipse.equinox.p2.ui.sdk;singleton:=true
5-
Bundle-Version: 1.3.300.qualifier
5+
Bundle-Version: 1.3.400.qualifier
66
Bundle-Activator: org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKUIActivator
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ protected IStatus run(IProgressMonitor monitor) {
115115
}
116116
});
117117

118-
var certificates = AuthorityChecker.getCertificates(uris, monitor);
118+
var certificates = authorityChecker.getCertificates(uris, monitor);
119119
authorityCertificates.putAll(certificates);
120120

121121
if (!parent.isDisposed()) {

features/org.eclipse.equinox.p2.core.feature/feature.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<feature
33
id="org.eclipse.equinox.p2.core.feature"
44
label="%featureName"
5-
version="1.7.400.qualifier"
5+
version="1.7.500.qualifier"
66
provider-name="%providerName"
77
license-feature="org.eclipse.license"
88
license-feature-version="0.0.0">

features/org.eclipse.equinox.p2.discovery.feature/feature.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<feature
33
id="org.eclipse.equinox.p2.discovery.feature"
44
label="%featureName"
5-
version="1.3.600.qualifier"
5+
version="1.3.700.qualifier"
66
provider-name="%providerName"
77
license-feature="org.eclipse.license"
88
license-feature-version="0.0.0">

0 commit comments

Comments
 (0)