Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2021-11-09 20:20:45 +0000
committerMickael Istria2021-11-29 10:28:25 +0000
commitf72e589913dd61ad3ad27839a0393ce143d2a9fa (patch)
tree1bfc8ce9e50e0c9f585ac0906a808772a21fd8e1
parent9ab8beb9260b22ae3196a48070b908034a2adae0 (diff)
downloadrt.equinox.p2-f72e589913dd61ad3ad27839a0393ce143d2a9fa.tar.gz
rt.equinox.p2-f72e589913dd61ad3ad27839a0393ce143d2a9fa.tar.xz
rt.equinox.p2-f72e589913dd61ad3ad27839a0393ce143d2a9fa.zip
Bug 577193 - Support addition/removal of trusted PGP keysI20211129-1800
Change-Id: I429645e308d805a4511828dfab18f7864fc01e1f Reviewed-on: https://git.eclipse.org/r/c/equinox/rt.equinox.p2/+/187562 Tested-by: Equinox Bot <equinox-bot@eclipse.org> Reviewed-by: Mickael Istria <mistria@redhat.com>
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/pom.xml2
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPPublicKeyStore.java125
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java57
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF2
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/pom.xml2
-rw-r--r--bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/CertificateChecker.java62
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPVerifierTest.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF3
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml2
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java74
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties6
-rw-r--r--features/org.eclipse.equinox.p2.core.feature/feature.xml2
-rw-r--r--features/org.eclipse.equinox.p2.core.feature/pom.xml2
-rw-r--r--features/org.eclipse.equinox.p2.extras.feature/feature.xml2
-rw-r--r--features/org.eclipse.equinox.p2.extras.feature/pom.xml2
-rw-r--r--features/org.eclipse.equinox.p2.rcp.feature/feature.xml2
-rw-r--r--features/org.eclipse.equinox.p2.rcp.feature/pom.xml2
-rw-r--r--features/org.eclipse.equinox.p2.sdk/feature.xml2
-rw-r--r--features/org.eclipse.equinox.p2.sdk/pom.xml2
-rw-r--r--features/org.eclipse.equinox.p2.user.ui/feature.xml2
-rw-r--r--features/org.eclipse.equinox.p2.user.ui/pom.xml2
23 files changed, 262 insertions, 102 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
index f7fc2091a..49e639b77 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.equinox.p2.artifact.repository;singleton:=true
-Bundle-Version: 1.4.300.qualifier
+Bundle-Version: 1.4.400.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.artifact.repository.Activator
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -10,7 +10,7 @@ Export-Package: org.eclipse.equinox.internal.p2.artifact.processing;x-friends:="
org.eclipse.equinox.internal.p2.artifact.processors.checksum;x-friends:="org.eclipse.equinox.p2.publisher",
org.eclipse.equinox.internal.p2.artifact.processors.md5;x-internal:=true,
org.eclipse.equinox.internal.p2.artifact.processors.pack200;x-friends:="org.eclipse.equinox.p2.artifact.processors,org.eclipse.equinox.p2.artifact.optimizers",
- org.eclipse.equinox.internal.p2.artifact.processors.pgp;x-friends:="org.eclipse.equinox.p2.engine",
+ org.eclipse.equinox.internal.p2.artifact.processors.pgp;x-friends:="org.eclipse.equinox.p2.engine,org.eclipse.equinox.p2.ui.sdk",
org.eclipse.equinox.internal.p2.artifact.repository;
x-friends:="org.eclipse.equinox.p2.publisher,
org.eclipse.equinox.p2.reconciler.dropins,
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/pom.xml b/bundles/org.eclipse.equinox.p2.artifact.repository/pom.xml
index 79eb5804e..896b53571 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/pom.xml
@@ -9,6 +9,6 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.artifact.repository</artifactId>
- <version>1.4.300-SNAPSHOT</version>
+ <version>1.4.400-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPPublicKeyStore.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPPublicKeyStore.java
new file mode 100644
index 000000000..3aff39c66
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPPublicKeyStore.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Red Hat Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.artifact.processors.pgp;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.function.Consumer;
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.openpgp.*;
+import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+
+public class PGPPublicKeyStore {
+ private Map<Long, PGPPublicKey> keys = new HashMap<>();
+
+ public PGPPublicKey addKey(PGPPublicKey key) {
+ if (key == null) {
+ return null;
+ }
+ PGPPublicKey alreadyStoredKey = keys.putIfAbsent(key.getKeyID(), key);
+ return alreadyStoredKey == null ? key : alreadyStoredKey;
+ }
+
+ public PGPPublicKey getKey(long id) {
+ return keys.get(id);
+ }
+
+ public void addKeys(String... armoredPublicKeys) {
+ for (String armoredKey : armoredPublicKeys) {
+ if (armoredKey != null) {
+ PGPPublicKeyStore.readPublicKeys(armoredKey).forEach(this::addKey);
+ }
+ }
+ }
+
+ /**
+ * Test only
+ */
+ public void clear() {
+ keys.clear();
+ }
+
+ public Collection<PGPPublicKey> all() {
+ return Collections.unmodifiableCollection(keys.values());
+ }
+
+ public boolean isEmpty() {
+ return keys.isEmpty();
+ }
+
+ public String toArmoredString() throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ArmoredOutputStream armoredOut = new ArmoredOutputStream(out);
+ // PGPPublicKeyRing ring = new PGPPublicKeyRing(new ArrayList<>(keys.values()));
+ // ring.encode(armoredOut);
+ for (PGPPublicKey key : keys.values()) {
+ key.encode(armoredOut);
+ }
+ armoredOut.close();
+ out.close();
+ return new String(out.toByteArray(), StandardCharsets.US_ASCII);
+ }
+
+ public void remove(PGPPublicKey selectedKey) {
+ keys.remove(selectedKey.getKeyID());
+ }
+
+ public void add(File file) {
+ try (InputStream stream = new FileInputStream(file)) {
+ readPublicKeys(stream).forEach(this::addKey);
+ } catch (IOException e) {
+ // TODO: how to log?
+ }
+ }
+
+ public static Set<PGPPublicKey> readPublicKeys(InputStream input) throws IOException {
+ return readPublicKeys(new String(input.readAllBytes(), StandardCharsets.US_ASCII));
+ }
+
+ public static Set<PGPPublicKey> readPublicKeys(String armoredPublicKeyring) {
+ if (armoredPublicKeyring == null) {
+ return Set.of();
+ }
+ Set<PGPPublicKey> res = new HashSet<>();
+ try (InputStream stream = PGPUtil.getDecoderStream(new ByteArrayInputStream(
+ PGPSignatureVerifier.unnormalizedPGPProperty(armoredPublicKeyring).getBytes()))) {
+ new JcaPGPObjectFactory(stream).forEach(o -> {
+ if (o instanceof PGPPublicKeyRingCollection) {
+ collectKeys((PGPPublicKeyRingCollection) o, res::add);
+ }
+ if (o instanceof PGPPublicKeyRing) {
+ collectKeys((PGPPublicKeyRing) o, res::add);
+ }
+ if (o instanceof PGPPublicKey) {
+ res.add((PGPPublicKey) o);
+ }
+ });
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e));
+ }
+ return res;
+
+ }
+
+ private static void collectKeys(PGPPublicKeyRingCollection pgpPublicKeyRingCollection,
+ Consumer<PGPPublicKey> collector) {
+ pgpPublicKeyRingCollection.forEach(keyring -> collectKeys(keyring, collector));
+ }
+
+ private static void collectKeys(PGPPublicKeyRing pgpPublicKeyRing, Consumer<PGPPublicKey> collector) {
+ pgpPublicKeyRing.getPublicKeys().forEachRemaining(collector::accept);
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java
index 05bbc2398..d752d1b61 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/pgp/PGPSignatureVerifier.java
@@ -15,11 +15,9 @@ import java.util.*;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.*;
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
-import org.bouncycastle.openpgp.bc.BcPGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
-import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.repository.artifact.*;
@@ -39,38 +37,7 @@ public final class PGPSignatureVerifier extends ProcessingStep {
*/
public static final String ID = "org.eclipse.equinox.p2.processing.PGPSignatureCheck"; //$NON-NLS-1$
- public static class PGPPublicKeyStore {
- private Map<Long, PGPPublicKey> keys = new HashMap<>();
-
- public PGPPublicKey addKey(PGPPublicKey key) {
- if (key == null) {
- return null;
- }
- PGPPublicKey alreadyStoredKey = keys.putIfAbsent(key.getKeyID(), key);
- return alreadyStoredKey == null ? key : alreadyStoredKey;
- }
-
- public PGPPublicKey getKey(long id) {
- return keys.get(id);
- }
-
- public void addKeys(String... armoredPublicKeys) {
- for (String armoredKey : armoredPublicKeys) {
- if (armoredKey != null) {
- readPublicKeys(armoredKey).forEach(this::addKey);
- }
- }
- }
-
- /**
- * Test only
- */
- public void clear() {
- keys.clear();
- }
- }
-
- public static final PGPPublicKeyStore keystore = new PGPPublicKeyStore();
+ public static final PGPPublicKeyStore KNOWN_KEYS = new PGPPublicKeyStore();
public static final String PGP_SIGNER_KEYS_PROPERTY_NAME = "pgp.publicKeys"; //$NON-NLS-1$
public static final String PGP_SIGNATURES_PROPERTY_NAME = "pgp.signatures"; //$NON-NLS-1$
@@ -127,10 +94,10 @@ public final class PGPSignatureVerifier extends ProcessingStep {
}
IArtifactRepository repository = context.getRepository();
- keystore.addKeys(context.getProperty(PGP_SIGNER_KEYS_PROPERTY_NAME),
+ KNOWN_KEYS.addKeys(context.getProperty(PGP_SIGNER_KEYS_PROPERTY_NAME),
repository != null ? repository.getProperty(PGP_SIGNER_KEYS_PROPERTY_NAME) : null);
for (PGPSignature signature : signaturesToVerify) {
- PGPPublicKey publicKey = keystore.getKey(signature.getKeyID());
+ PGPPublicKey publicKey = KNOWN_KEYS.getKey(signature.getKeyID());
if (publicKey == null) {
setStatus(new Status(IStatus.ERROR, Activator.ID,
NLS.bind(Messages.Error_publicKeyNotFound, Long.toHexString(signature.getKeyID()))));
@@ -152,7 +119,7 @@ public final class PGPSignatureVerifier extends ProcessingStep {
* @param armoredPGPBlock the PGP block, in armored form
* @return fixed PGP armored blocks
*/
- private static String unnormalizedPGPProperty(String armoredPGPBlock) {
+ static String unnormalizedPGPProperty(String armoredPGPBlock) {
if (armoredPGPBlock == null) {
return null;
}
@@ -166,22 +133,6 @@ public final class PGPSignatureVerifier extends ProcessingStep {
.replace("-----END\nPGP\nPUBLIC\nKEY\nBLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"); //$NON-NLS-1$ //$NON-NLS-2$
}
- public static Set<PGPPublicKey> readPublicKeys(String armoredPublicKeyring) {
- if (armoredPublicKeyring == null) {
- return Set.of();
- }
- Set<PGPPublicKey> res = new HashSet<>();
- try (InputStream stream = PGPUtil
- .getDecoderStream(new ByteArrayInputStream(unnormalizedPGPProperty(armoredPublicKeyring).getBytes()))) {
- PGPPublicKeyRingCollection pgpPub = new BcPGPPublicKeyRingCollection(stream);
- pgpPub.getKeyRings().forEachRemaining(kRing -> kRing.getPublicKeys().forEachRemaining(res::add));
- } catch (IOException | PGPException e) {
- LogHelper.log(new Status(IStatus.ERROR, Activator.ID, e.getMessage(), e));
- }
- return res;
-
- }
-
@Override
public void write(int b) {
if (signaturesToVerify != null) {
diff --git a/bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF
index 439758603..d1e7137aa 100644
--- a/bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.engine/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.equinox.p2.engine;singleton:=true
-Bundle-Version: 2.7.200.qualifier
+Bundle-Version: 2.7.300.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.engine.EngineActivator
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.equinox.p2.engine/pom.xml b/bundles/org.eclipse.equinox.p2.engine/pom.xml
index 00514163d..cbf8386be 100644
--- a/bundles/org.eclipse.equinox.p2.engine/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.engine/pom.xml
@@ -9,6 +9,6 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.engine</artifactId>
- <version>2.7.200-SNAPSHOT</version>
+ <version>2.7.300-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/CertificateChecker.java b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/CertificateChecker.java
index 12c3fd3d2..15943a47c 100644
--- a/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/CertificateChecker.java
+++ b/bundles/org.eclipse.equinox.p2.engine/src/org/eclipse/equinox/internal/p2/engine/phases/CertificateChecker.java
@@ -21,21 +21,21 @@ import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.bouncycastle.openpgp.*;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPPublicKeyStore;
import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPSignatureVerifier;
import org.eclipse.equinox.internal.p2.engine.*;
-import org.eclipse.equinox.p2.core.IProvisioningAgent;
-import org.eclipse.equinox.p2.core.UIServices;
+import org.eclipse.equinox.p2.core.*;
import org.eclipse.equinox.p2.core.UIServices.TrustInfo;
-import org.eclipse.equinox.p2.engine.IProfile;
-import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.engine.*;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.osgi.service.security.TrustEngine;
import org.eclipse.osgi.signedcontent.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.prefs.BackingStoreException;
import org.osgi.util.tracker.ServiceTracker;
/**
@@ -54,7 +54,7 @@ public class CertificateChecker {
private Map<IArtifactDescriptor, File> artifacts = new HashMap<>();
private final IProvisioningAgent agent;
- private Set<PGPPublicKey> trustedKeys;
+ private PGPPublicKeyStore trustedKeys;
public CertificateChecker() {
this(null);
@@ -117,7 +117,7 @@ public class CertificateChecker {
trustedKeys = buildPGPTrustore();
}
if (trustedKeysIds.isEmpty() && !trustedKeys.isEmpty()) {
- trustedKeysIds.addAll(trustedKeys.stream()
+ trustedKeysIds.addAll(trustedKeys.all().stream()
.map(PGPPublicKey::getKeyID).map(Long::valueOf).collect(Collectors.toSet()));
}
if (signatures.stream().map(PGPSignature::getKeyID).noneMatch(trustedKeysIds::contains)) {
@@ -221,21 +221,33 @@ public class CertificateChecker {
}
// If we should persist the trusted certificates, add them to the trust engine
if (trustInfo.persistTrust()) {
- return persistTrustedCertificates(trustedCertificates);
- // do not persist PGP key at the moment
+ IStatus certifactesStatus = trustInfo.getTrustedCertificates().length == 0 ? null
+ : persistTrustedCertificates(trustedCertificates);
+ trustInfo.getTrustedPGPKeys().forEach(trustedKeys::addKey);
+ IStatus pgpStatus = trustInfo.getTrustedPGPKeys().isEmpty() ? null : persistTrustedKeys(trustedKeys);
+ if (pgpStatus == null) {
+ return certifactesStatus;
+ }
+ if (certifactesStatus == null) {
+ return pgpStatus;
+ }
+ return new MultiStatus(getClass(), IStatus.OK, new IStatus[] { pgpStatus, certifactesStatus },
+ pgpStatus.getMessage() + '\n' + certifactesStatus.getMessage(), null);
}
return status;
}
+
private PGPPublicKey findKey(long id, IArtifactDescriptor artifact) {
- PGPPublicKey key = PGPSignatureVerifier.keystore.getKey(id);
+ PGPPublicKey key = PGPSignatureVerifier.KNOWN_KEYS.getKey(id);
if (key != null) {
return key;
}
// in case keys from artifact were not imported yet in keystore, add them
- PGPSignatureVerifier.keystore.addKeys(artifact.getProperty(PGPSignatureVerifier.PGP_SIGNER_KEYS_PROPERTY_NAME));
- return PGPSignatureVerifier.keystore.getKey(id);
+ PGPSignatureVerifier.KNOWN_KEYS
+ .addKeys(artifact.getProperty(PGPSignatureVerifier.PGP_SIGNER_KEYS_PROPERTY_NAME));
+ return PGPSignatureVerifier.KNOWN_KEYS.getKey(id);
}
private IStatus persistTrustedCertificates(Certificate[] trustedCertificates) {
@@ -286,19 +298,33 @@ public class CertificateChecker {
artifacts.putAll(toAdd);
}
- public Set<PGPPublicKey> buildPGPTrustore() {
+ public PGPPublicKeyStore buildPGPTrustore() {
+ PGPPublicKeyStore trustStore = new PGPPublicKeyStore();
IProfile profile = agent.getService(IProfileRegistry.class).getProfile(IProfileRegistry.SELF);
- Set<PGPPublicKey> store = new HashSet<>(
- PGPSignatureVerifier.readPublicKeys(profile.getProperty(TRUSTED_KEY_STORE_PROPERTY)));
+ trustStore.addKeys(profile.getProperty(TRUSTED_KEY_STORE_PROPERTY));
+ ProfileScope profileScope = new ProfileScope(agent.getService(IAgentLocation.class), profile.getProfileId());
+ trustStore.addKeys(profileScope.getNode(EngineActivator.ID).get(TRUSTED_KEY_STORE_PROPERTY, null));
//// SECURITY ISSUE: next lines become an attack vector as we have no guarantee
//// the metadata of those IUs is safe/were signed.
//// https://bugs.eclipse.org/bugs/show_bug.cgi?id=576705#c4
// profile.query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).forEach(
// iu ->
// store.addAll(PGPSignatureVerifier.readPublicKeys(iu.getProperty(TRUSTED_KEY_STORE_PROPERTY))));
- store.forEach(PGPSignatureVerifier.keystore::addKey);
- return store;
+ trustStore.all().forEach(PGPSignatureVerifier.KNOWN_KEYS::addKey);
+ return trustStore;
}
+ public IStatus persistTrustedKeys(PGPPublicKeyStore trustStore) {
+ IProfile profile = agent.getService(IProfileRegistry.class).getProfile(IProfileRegistry.SELF);
+ ProfileScope profileScope = new ProfileScope(agent.getService(IAgentLocation.class), profile.getProfileId());
+ IEclipsePreferences node = profileScope.getNode(EngineActivator.ID);
+ try {
+ node.put(TRUSTED_KEY_STORE_PROPERTY, trustStore.toArmoredString());
+ node.flush();
+ return Status.OK_STATUS;
+ } catch (IOException | BackingStoreException ex) {
+ return new Status(IStatus.ERROR, EngineActivator.ID, ex.getMessage(), ex);
+ }
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPVerifierTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPVerifierTest.java
index 161675ce2..c010af306 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPVerifierTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/PGPVerifierTest.java
@@ -30,7 +30,7 @@ public class PGPVerifierTest extends AbstractProvisioningTest {
@Before
public void setUp() throws Exception {
super.setUp();
- PGPSignatureVerifier.keystore.clear();
+ PGPSignatureVerifier.KNOWN_KEYS.clear();
}
private void loadPGPTestRepo(String repoName) throws Exception {
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
index cc9e868d8..988cfdd1b 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %bundleName
Bundle-SymbolicName: org.eclipse.equinox.p2.ui.sdk;singleton:=true
-Bundle-Version: 1.2.2.qualifier
+Bundle-Version: 1.2.3.qualifier
Bundle-Activator: org.eclipse.equinox.internal.p2.ui.sdk.ProvSDKUIActivator
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -18,6 +18,7 @@ Import-Package: javax.xml.parsers,
org.eclipse.compare.structuremergeviewer;resolution:=optional,
org.eclipse.equinox.internal.p2.engine.phases,
org.eclipse.equinox.p2.core;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.internal.p2.artifact.processors.pgp,
org.eclipse.equinox.p2.engine;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.engine.query;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.metadata;version="[2.0.0,3.0.0)",
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml b/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
index 4bbc8001b..32f6d437e 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/pom.xml
@@ -9,6 +9,6 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.ui.sdk</artifactId>
- <version>1.2.2-SNAPSHOT</version>
+ <version>1.2.3-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
index 4c73980f4..bf0a1956c 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/ProvSDKMessages.java
@@ -56,5 +56,8 @@ public class ProvSDKMessages extends NLS {
public static String TrustPreferencePage_userColumn;
public static String TrustPreferencePage_fileExportTitle;
public static String TrustPreferencePage_pgpIntro;
+ public static String TrustPreferencePage_fileImportTitle;
+ public static String TrustPreferencePage_addPGPKeyButtonLabel;
+ public static String TrustPreferencePage_removePGPKeyButtonLabel;
}
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java
index 4b4c2439c..417ba2d68 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/TrustPreferencePage.java
@@ -17,6 +17,7 @@ import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPPublicKeyStore;
import org.eclipse.equinox.internal.p2.engine.phases.CertificateChecker;
import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
import org.eclipse.jface.dialogs.IDialogConstants;
@@ -33,6 +34,11 @@ import org.eclipse.ui.IWorkbenchPreferencePage;
public class TrustPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
+ private CertificateChecker certificateChecker;
+ private PGPPublicKeyStore trustedKeys;
+ private boolean dirty = false;
+ private TableViewer viewer;
+
public TrustPreferencePage() {
super(ProvSDKMessages.TrustPreferencePage_title);
}
@@ -51,7 +57,7 @@ public class TrustPreferencePage extends PreferencePage implements IWorkbenchPre
pgpLabel.setText(ProvSDKMessages.TrustPreferencePage_pgpIntro);
res.setLayout(new GridLayout(2, false));
- TableViewer viewer = new TableViewer(res);
+ viewer = new TableViewer(res);
viewer.getTable().setHeaderVisible(true);
viewer.setContentProvider(new ArrayContentProvider());
TableViewerColumn idColumn = new TableViewerColumn(viewer, SWT.NONE);
@@ -75,23 +81,19 @@ public class TrustPreferencePage extends PreferencePage implements IWorkbenchPre
userColumn.getColumn().setWidth(400);
userColumn.getColumn().setText(ProvSDKMessages.TrustPreferencePage_userColumn);
viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- viewer.setInput(
- new CertificateChecker(ProvSDKUIActivator.getDefault().getProvisioningAgent()).buildPGPTrustore());
+ certificateChecker = new CertificateChecker(ProvSDKUIActivator.getDefault().getProvisioningAgent());
+ trustedKeys = certificateChecker.buildPGPTrustore();
+ viewer.setInput(trustedKeys.all());
Composite buttonComposite = createVerticalButtonBar(res);
buttonComposite.setLayoutData(new GridData(SWT.DEFAULT, SWT.BEGINNING, false, false));
Button exportButton = new Button(buttonComposite, SWT.PUSH);
exportButton.setText(ProvSDKMessages.TrustPreferencePage_export);
setVerticalButtonLayoutData(exportButton);
exportButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
- ISelection sel = viewer.getSelection();
- if (!(sel instanceof IStructuredSelection)) {
- return;
- }
- Object o = ((IStructuredSelection)sel).getFirstElement();
- if (!(o instanceof PGPPublicKey)) {
+ PGPPublicKey key = getSelectedKey();
+ if (key == null) {
return;
}
- PGPPublicKey key = (PGPPublicKey)o;
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setText(ProvSDKMessages.TrustPreferencePage_fileExportTitle);
dialog.setFilterExtensions(new String[] { "*.asc" }); //$NON-NLS-1$
@@ -108,11 +110,50 @@ public class TrustPreferencePage extends PreferencePage implements IWorkbenchPre
.log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, ex.getMessage(), ex));
}
}));
- viewer.addPostSelectionChangedListener(e -> exportButton.setEnabled(!e.getSelection().isEmpty()));
- exportButton.setEnabled(!viewer.getSelection().isEmpty());
+ Button addButton = new Button(buttonComposite, SWT.PUSH);
+ addButton.setText(ProvSDKMessages.TrustPreferencePage_addPGPKeyButtonLabel);
+ addButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
+ FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
+ dialog.setText(ProvSDKMessages.TrustPreferencePage_fileImportTitle);
+ dialog.setFilterExtensions(new String[] { "*.asc" }); //$NON-NLS-1$
+ String path = dialog.open();
+ if (path == null) {
+ return;
+ }
+ trustedKeys.add(new File(path));
+ viewer.setInput(trustedKeys.all());
+ dirty = true;
+ }));
+ setVerticalButtonLayoutData(addButton);
+ Button removeButton = new Button(buttonComposite, SWT.PUSH);
+ removeButton.setText(ProvSDKMessages.TrustPreferencePage_removePGPKeyButtonLabel);
+ removeButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
+ trustedKeys.remove(getSelectedKey());
+ viewer.setInput(trustedKeys.all());
+ dirty = true;
+ }));
+ setVerticalButtonLayoutData(removeButton);
+ viewer.addPostSelectionChangedListener(e -> {
+ exportButton.setEnabled(getSelectedKey() != null);
+ removeButton.setEnabled(getSelectedKey() != null);
+ });
+ exportButton.setEnabled(getSelectedKey() != null);
+ removeButton.setEnabled(getSelectedKey() != null);
return res;
}
+ private PGPPublicKey getSelectedKey() {
+ ISelection sel = viewer.getSelection();
+ if (!(sel instanceof IStructuredSelection)) {
+ return null;
+ }
+ Object o = ((IStructuredSelection) sel).getFirstElement();
+ if (!(o instanceof PGPPublicKey)) {
+ return null;
+ }
+ return (PGPPublicKey) o;
+ }
+
private Composite createVerticalButtonBar(Composite parent) {
// Create composite.
Composite composite = new Composite(parent, SWT.NONE);
@@ -139,4 +180,13 @@ public class TrustPreferencePage extends PreferencePage implements IWorkbenchPre
button.setLayoutData(data);
return data;
}
+
+ @Override
+ public boolean performOk() {
+ if (dirty) {
+ return certificateChecker.persistTrustedKeys(trustedKeys).isOK();
+ }
+ return true;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
index 4e79e3211..0e344af3d 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/messages.properties
@@ -36,9 +36,13 @@ UpdateHandler_ProgressTaskName=Checking for updates...
RemediationOperation_ResolveJobName=Searching alternate solutions...
RemediationOperation_ResolveJobTask=Some items cannot be at the highest version. Searching for the highest common denominator ...
TrustPreferencePage_title=Trust
-TrustPreferencePage_export=E&xport...
+TrustPreferencePage_export=\uD83D\uDCE5 E&xport...
TrustPreferencePage_idColumn=Id
TrustPreferencePage_userColumn=User
TrustPreferencePage_fileExportTitle=Export PGP public key
+TrustPreferencePage_fileImportTitle=Import PGP public key to trust
+TrustPreferencePage_addPGPKeyButtonLabel=\u2795 &Add...
+TrustPreferencePage_removePGPKeyButtonLabel=\uD83D\uDDD1\uFE0F &Remove
+
TrustPreferencePage_pgpIntro=The following PGP public keys are considered as trusted.\n\
Artifacts that are signed and verified by one of those keys will be trusted and installed without further trust confirmation request. \ No newline at end of file
diff --git a/features/org.eclipse.equinox.p2.core.feature/feature.xml b/features/org.eclipse.equinox.p2.core.feature/feature.xml
index fdad4dbc9..f8cffb089 100644
--- a/features/org.eclipse.equinox.p2.core.feature/feature.xml
+++ b/features/org.eclipse.equinox.p2.core.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.equinox.p2.core.feature"
label="%featureName"
- version="1.6.1200.qualifier"
+ version="1.6.1300.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
diff --git a/features/org.eclipse.equinox.p2.core.feature/pom.xml b/features/org.eclipse.equinox.p2.core.feature/pom.xml
index b38d01548..1420cd178 100644
--- a/features/org.eclipse.equinox.p2.core.feature/pom.xml
+++ b/features/org.eclipse.equinox.p2.core.feature/pom.xml
@@ -20,7 +20,7 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.core.feature</artifactId>
- <version>1.6.1200-SNAPSHOT</version>
+ <version>1.6.1300-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
diff --git a/features/org.eclipse.equinox.p2.extras.feature/feature.xml b/features/org.eclipse.equinox.p2.extras.feature/feature.xml
index 2449f4144..ac67f7b30 100644
--- a/features/org.eclipse.equinox.p2.extras.feature/feature.xml
+++ b/features/org.eclipse.equinox.p2.extras.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.equinox.p2.extras.feature"
label="%featureName"
- version="1.4.1400.qualifier"
+ version="1.4.1500.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
diff --git a/features/org.eclipse.equinox.p2.extras.feature/pom.xml b/features/org.eclipse.equinox.p2.extras.feature/pom.xml
index 1b751b496..200e682ad 100644
--- a/features/org.eclipse.equinox.p2.extras.feature/pom.xml
+++ b/features/org.eclipse.equinox.p2.extras.feature/pom.xml
@@ -19,7 +19,7 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.extras.feature</artifactId>
- <version>1.4.1400-SNAPSHOT</version>
+ <version>1.4.1500-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
<build>
diff --git a/features/org.eclipse.equinox.p2.rcp.feature/feature.xml b/features/org.eclipse.equinox.p2.rcp.feature/feature.xml
index a5fe82747..f07c42fa7 100644
--- a/features/org.eclipse.equinox.p2.rcp.feature/feature.xml
+++ b/features/org.eclipse.equinox.p2.rcp.feature/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.equinox.p2.rcp.feature"
label="%featureName"
- version="1.4.1400.qualifier"
+ version="1.4.1500.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
diff --git a/features/org.eclipse.equinox.p2.rcp.feature/pom.xml b/features/org.eclipse.equinox.p2.rcp.feature/pom.xml
index 58a3f6117..7abade620 100644
--- a/features/org.eclipse.equinox.p2.rcp.feature/pom.xml
+++ b/features/org.eclipse.equinox.p2.rcp.feature/pom.xml
@@ -20,7 +20,7 @@
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.rcp.feature</artifactId>
- <version>1.4.1400-SNAPSHOT</version>
+ <version>1.4.1500-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
<build>
diff --git a/features/org.eclipse.equinox.p2.sdk/feature.xml b/features/org.eclipse.equinox.p2.sdk/feature.xml
index fa259be4f..3f87a10f4 100644
--- a/features/org.eclipse.equinox.p2.sdk/feature.xml
+++ b/features/org.eclipse.equinox.p2.sdk/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.equinox.p2.sdk"
label="%featureName"
- version="3.11.1400.qualifier"
+ version="3.11.1500.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
diff --git a/features/org.eclipse.equinox.p2.sdk/pom.xml b/features/org.eclipse.equinox.p2.sdk/pom.xml
index 3fcde857a..ce34c2cd4 100644
--- a/features/org.eclipse.equinox.p2.sdk/pom.xml
+++ b/features/org.eclipse.equinox.p2.sdk/pom.xml
@@ -20,6 +20,6 @@
</parent>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.sdk</artifactId>
- <version>3.11.1400-SNAPSHOT</version>
+ <version>3.11.1500-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
</project>
diff --git a/features/org.eclipse.equinox.p2.user.ui/feature.xml b/features/org.eclipse.equinox.p2.user.ui/feature.xml
index 53903347f..415f30d94 100644
--- a/features/org.eclipse.equinox.p2.user.ui/feature.xml
+++ b/features/org.eclipse.equinox.p2.user.ui/feature.xml
@@ -2,7 +2,7 @@
<feature
id="org.eclipse.equinox.p2.user.ui"
label="%featureName"
- version="2.4.1400.qualifier"
+ version="2.4.1500.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
diff --git a/features/org.eclipse.equinox.p2.user.ui/pom.xml b/features/org.eclipse.equinox.p2.user.ui/pom.xml
index c281a3a27..7840daa87 100644
--- a/features/org.eclipse.equinox.p2.user.ui/pom.xml
+++ b/features/org.eclipse.equinox.p2.user.ui/pom.xml
@@ -20,7 +20,7 @@
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.p2.user.ui</artifactId>
- <version>2.4.1400-SNAPSHOT</version>
+ <version>2.4.1500-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
<build>

Back to the top