Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2')
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java47
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/IArtifactUIServices.java96
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/spi/PGPPublicKeyService.java243
3 files changed, 363 insertions, 23 deletions
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
index 9b5cd4d9b..2403402ac 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
@@ -23,7 +23,7 @@ import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
* descriptor defines the artifact it contains, as well as any processing steps that
* must be performed when the artifact is transferred out of the repository (such
* as decompression, error checking, etc).
- *
+ *
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients. Instead subclass the {@link ArtifactDescriptor} class
* @since 2.0
@@ -34,37 +34,36 @@ public interface IArtifactDescriptor {
* An artifact descriptor property (value "download.size") indicating the number
* of bytes that will be transferred when this artifact is transferred out of the repository.
*/
- public static final String DOWNLOAD_SIZE = "download.size"; //$NON-NLS-1$
+ String DOWNLOAD_SIZE = "download.size"; //$NON-NLS-1$
/**
* An artifact descriptor property (value "artifact.size") indicating the size in
* bytes of the artifact in its native format (after processing steps have been applied).
*/
- public static final String ARTIFACT_SIZE = "artifact.size"; //$NON-NLS-1$
+ String ARTIFACT_SIZE = "artifact.size"; //$NON-NLS-1$
/**
* A prefix of an artifact descriptor properties storing checksum
* of the artifact bytes that are transferred.
* @since 2.4
*/
- public static final String DOWNLOAD_CHECKSUM = "download.checksum"; //$NON-NLS-1$
+ String DOWNLOAD_CHECKSUM = "download.checksum"; //$NON-NLS-1$
/**
* An artifact descriptor property (value "download.md5") indicating the MD5
* checksum of the artifact bytes that are transferred.
* @see #DOWNLOAD_CHECKSUM
*/
- @Deprecated
- public static final String DOWNLOAD_MD5 = "download.md5"; //$NON-NLS-1$
+ @Deprecated String DOWNLOAD_MD5 = "download.md5"; //$NON-NLS-1$
/**
- * An artifact descriptor property (value "download.contentType") indicating the
+ * An artifact descriptor property (value "download.contentType") indicating the
* content type of the artifact bytes that are transferred.
*/
- public static final String DOWNLOAD_CONTENTTYPE = "download.contentType"; //$NON-NLS-1$
+ String DOWNLOAD_CONTENTTYPE = "download.contentType"; //$NON-NLS-1$
/**
* An content type (value "application/zip") indicating the content is a zip file.
*/
- public static final String TYPE_ZIP = "application/zip"; //$NON-NLS-1$
+ String TYPE_ZIP = "application/zip"; //$NON-NLS-1$
/**
* A prefix of an artifact descriptor property storing list of
@@ -72,7 +71,7 @@ public interface IArtifactDescriptor {
* been applied).
* @since 2.4
*/
- public static final String ARTIFACT_CHECKSUM = "artifact.checksum"; //$NON-NLS-1$
+ String ARTIFACT_CHECKSUM = "artifact.checksum"; //$NON-NLS-1$
/**
* An artifact descriptor property (value "artifact.md5") indicating the MD5
@@ -80,59 +79,61 @@ public interface IArtifactDescriptor {
* been applied).
* @see #ARTIFACT_CHECKSUM
*/
- @Deprecated
- public static final String ARTIFACT_MD5 = "artifact.md5"; //$NON-NLS-1$
+ @Deprecated String ARTIFACT_MD5 = "artifact.md5"; //$NON-NLS-1$
/**
* An artifact descriptor property (value "format") indicating the storage format
* of the artifact in the repository.
* @see #FORMAT_PACKED
*/
- public static final String FORMAT = "format"; //$NON-NLS-1$
+ String FORMAT = "format"; //$NON-NLS-1$
/**
* A property value for the {@link #FORMAT} artifact descriptor property (value "packed")
* indicating the storage format is using pack200 compression.
* @see #FORMAT
+ * @noreference This field is not intended to be referenced by clients.
+ *
+ * @deprecated See <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=572043">bug</a> for details.
*/
- public static final String FORMAT_PACKED = "packed"; //$NON-NLS-1$
+ @Deprecated(forRemoval = true, since = "2.5.0") String FORMAT_PACKED = "packed"; //$NON-NLS-1$
/**
* Return the key for the artifact described by this descriptor.
* @return the key associated with this descriptor
*/
- public abstract IArtifactKey getArtifactKey();
+ IArtifactKey getArtifactKey();
/**
- * Return the value of the given property in this descriptor <code>null</code>
+ * Return the value of the given property in this descriptor <code>null</code>
* is returned if no such property exists
* @param key the property key to look for
* @return the value of the given property or <code>null</code>
*/
- public abstract String getProperty(String key);
+ String getProperty(String key);
/**
* Returns a read-only collection of the properties of the artifact descriptor.
* @return the properties of this artifact descriptor.
*/
- public Map<String, String> getProperties();
+ Map<String, String> getProperties();
- /**
+ /**
* Return the list of processing steps associated with this descriptor.
* An empty set of steps implies that this descriptor describes a complete
* copy of the artifact in its native form. If one or more steps are present,
* they may be performed when the artifact is transferred from the repository
* that contains it.
- *
+ *
* @return the list of processing steps for this descriptor
*/
- public abstract IProcessingStepDescriptor[] getProcessingSteps();
+ IProcessingStepDescriptor[] getProcessingSteps();
/**
* Return the artifact repository that holds the artifact described by this descriptor.
* <code>null</code> is returned if this descriptor is not held in a repository.
- *
+ *
* @return the repository holding this artifact or <code>null</code> if none.
*/
- public abstract IArtifactRepository getRepository();
+ IArtifactRepository getRepository();
}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/IArtifactUIServices.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/IArtifactUIServices.java
new file mode 100644
index 000000000..b5cc328f5
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/spi/IArtifactUIServices.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Eclipse contributors 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.p2.repository.artifact.spi;
+
+import java.io.File;
+import java.security.cert.Certificate;
+import java.util.*;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.eclipse.equinox.p2.core.UIServices;
+import org.eclipse.equinox.p2.core.UIServices.TrustInfo;
+import org.eclipse.equinox.p2.metadata.IArtifactKey;
+
+/**
+ * An interface optionally implemented by {@link UIServices} to provide richer
+ * information for the users. In particular, the users often wish to know which
+ * artifacts are signed by which certificates or which keys when they are
+ * {@link UIServices#getTrustInfo(Certificate[][], Collection, String[])
+ * prompted} whether to trust such certificates or keys.
+ *
+ * @since 2.6
+ *
+ * @see UIServices#getTrustInfo(Certificate[][], Collection, String[])
+ */
+public interface IArtifactUIServices {
+
+ /**
+ * Opens a UI prompt to capture information about trusted content.
+ *
+ * @param untrustedCertificateChains a map from untrusted certificate chains to
+ * the set of keys of the artifacts signed by
+ * that chain.
+ * @param untrustedPGPKeys a map of untrusted PGP public keys to the
+ * set of keys of the artifacts signed by that
+ * key.
+ * @param unsignedArtifacts a set of keys of the artifacts that are not
+ * signed.
+ * @param artifactFiles a map from artifact keys to the file
+ * associated with that artifact key.
+ *
+ * @return the TrustInfo that describes the user's choices for trusting
+ * certificates, keys, and unsigned content.
+ *
+ * @see #getTrustInfo(UIServices, Map, Map, Set, Map)
+ * @see UIServices
+ */
+ TrustInfo getTrustInfo( //
+ Map<List<Certificate>, Set<IArtifactKey>> untrustedCertificateChains, //
+ Map<PGPPublicKey, Set<IArtifactKey>> untrustedPGPKeys, //
+ Set<IArtifactKey> unsignedArtifacts, //
+ Map<IArtifactKey, File> artifactFiles);
+
+ /**
+ * Opens a UI prompt to capture information about trusted content. This
+ * implementation is useful for delegating to an old-style
+ * {@link UIServices#getTrustInfo(Certificate[][], Collection, String[])
+ * UIServices implementation} that does not support the IArtifactUIServices
+ * interface.
+ *
+ * @param uiServices the delegate UI services.
+ * @param untrustedCertificateChains a map from untrusted certificate chains to
+ * the set of keys of the artifacts signed by
+ * that chain.
+ * @param untrustedPGPKeys a map of untrusted PGP public keys to the
+ * set of keys of the artifacts signed by that
+ * key.
+ * @param unsignedArtifacts a set of keys of the artifacts that are not
+ * signed.
+ * @param artifactFiles a map from artifact keys to the file
+ * associated with that artifact key.
+ *
+ * @return the TrustInfo that describes the user's choices for trusting
+ * certificates, keys, and unsigned content.
+ *
+ * @see #getTrustInfo(Map, Map, Set, Map)
+ * @see UIServices#getTrustInfo(Certificate[][], Collection, String[])
+ */
+ static TrustInfo getTrustInfo(UIServices uiServices, //
+ Map<List<Certificate>, Set<IArtifactKey>> untrustedCertificateChains, //
+ Map<PGPPublicKey, Set<IArtifactKey>> untrustedPGPKeys, //
+ Set<IArtifactKey> unsignedArtifacts, //
+ Map<IArtifactKey, File> artifactFiles) {
+ Certificate[][] unTrustedCertificateChainsArray = untrustedCertificateChains.keySet().stream()
+ .map(c -> c.toArray(Certificate[]::new)).toArray(Certificate[][]::new);
+ String[] details = unsignedArtifacts.isEmpty() ? null
+ : unsignedArtifacts.stream().map(artifactFiles::get).map(Objects::toString).toArray(String[]::new);
+ return uiServices.getTrustInfo(unTrustedCertificateChainsArray, untrustedPGPKeys.keySet(), details);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/spi/PGPPublicKeyService.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/spi/PGPPublicKeyService.java
new file mode 100644
index 000000000..6fbdff286
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/spi/PGPPublicKeyService.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2022 Eclipse contributors 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.p2.repository.spi;
+
+import java.util.*;
+import org.bouncycastle.openpgp.PGPPublicKey;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.util.encoders.Hex;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory;
+
+/**
+ * A service for managing and searching {@link PGPPublicKey keys}.
+ * Implementations may make use of a
+ * <a href="https://datatracker.ietf.org/doc/html/draft-shaw-openpgp-hkp-00">key
+ * server</a> to fetch up-to-date information about keys. Implementations should
+ * generally provide support for caching and efficient lookup of keys,
+ * especially lookup based on {@link PGPPublicKey#getKeyID() key ID} because
+ * signatures generally use {@link PGPSignature#getKeyID() key IDs} and this is
+ * the primary use case.
+ *
+ * <p>
+ * Implementors of this service are responsible for registering the
+ * implementation with the {@link IProvisioningAgent provisioning agent} either
+ * {@link IProvisioningAgent#registerService(String, Object) explicitly} or via
+ * an {@link IAgentServiceFactory agent service factory}.
+ * </p>
+ *
+ * @see PGPPublicKey#getKeyID()
+ * @see PGPSignature#getKeyID()
+ * @see IAgentServiceFactory
+ * @see IProvisioningAgent#registerService(String, Object)
+ *
+ * @since 2.6
+ */
+public abstract class PGPPublicKeyService {
+ /**
+ * The name used for obtaining a reference to the key service.
+ *
+ * @see IProvisioningAgent#getService(Class)
+ * @see IProvisioningAgent#getService(String)
+ */
+ public static final String SERVICE_NAME = PGPPublicKeyService.class.getName();
+
+ /**
+ * Returns the key associated with the given
+ * {@link PGPPublicKey#getFingerprint() fingerprint}.
+ *
+ * @param fingerprint the fingerprint for which to search.
+ * @return the key with the matching fingerprint.
+ *
+ * @see PGPPublicKey#getFingerprint()
+ */
+ public PGPPublicKey getKey(byte[] fingerprint) {
+ return getKey(toHex(fingerprint));
+ }
+
+ /**
+ * Returns the key associated with the given
+ * {@link PGPPublicKey#getFingerprint() fingerprint} represented as a
+ * {@link #toHex(byte[]) hexadecimal} string value.
+ *
+ * @param fingerprint the fingerprint for which to search.
+ * @return the key with the matching fingerprint.
+ *
+ * @see PGPPublicKey#getFingerprint()
+ * @see #toHex(byte[])
+ */
+ public abstract PGPPublicKey getKey(String fingerprint);
+
+ /**
+ * Returns the keys associated with the given {@link PGPPublicKey#getKeyID() key
+ * ID}. In general, key ID collisions are possible so implementations must be
+ * tolerant of that.
+ *
+ * @param keyID the key ID for which to search.
+ * @return the keys with the matching key IDs.
+ *
+ * @see PGPPublicKey#getKeyID()
+ * @see PGPSignature#getKeyID()
+ */
+ public abstract Collection<PGPPublicKey> getKeys(long keyID);
+
+ /**
+ * Adds the given key to this key service. An implementations may fetch more
+ * up-to-date information about this key from a key server and may return a
+ * different key than the one passed in here. In general an implementation may
+ * also return an existing key, with the same fingerprint, already known to the
+ * key service.
+ *
+ * @param key the key to add.
+ * @return the normalized key available in this key service.
+ */
+ public abstract PGPPublicKey addKey(PGPPublicKey key);
+
+ /**
+ * Returns the set of keys that have been verified to have signed the given key.
+ * These are the links in the web of trust.
+ *
+ * @param key the key for which to find keys that have signed it.
+ * @return the set of keys that have been verified to have signed the given key.
+ *
+ * @see PGPSignature#verifyCertification(String, PGPPublicKey)
+ * @see PGPSignature#verifyCertification(PGPPublicKey, PGPPublicKey)
+ */
+ public abstract Set<PGPPublicKey> getVerifiedCertifications(PGPPublicKey key);
+
+ /**
+ * If this key has a revocation signature that is verified to have been signed
+ * by the public key of that revocation signature, this returns the
+ * {@link PGPSignature#getCreationTime() creation time} of that signature,
+ * otherwise it returns <code>null</code>.
+ *
+ * @param key the key to test for revocation.
+ * @return when this key was verifiably revoked, or <code>null</code> if it is
+ * not revoked.
+ *
+ * @see PGPSignature#getKeyID()
+ * @see PGPPublicKey#hasRevocation()
+ * @see PGPSignature#getCreationTime()
+ * @see PGPSignature#KEY_REVOCATION
+ * @see PGPSignature#SUBKEY_REVOCATION
+ */
+ public abstract Date getVerifiedRevocationDate(PGPPublicKey key);
+
+ /**
+ * Returns whether the signature's {@link PGPSignature creation time} is before
+ * the key's {@link #getVerifiedRevocationDate(PGPPublicKey) verified revocation
+ * date}, if that key has one.
+ *
+ * @param signature the signature to test.
+ * @param key the corresponding key of this signature against which to
+ * test.
+ * @return <code>true</code> if the signature was created before the key was
+ * revoked or if the key is not revoked, <code>false</code> otherwise.
+ *
+ * @throws IllegalArgumentException if the signature's
+ * {@link PGPSignature#getKeyID() key} is not
+ * the same as the key's
+ * {@link PGPPublicKey#getKeyID() key ID}
+ */
+ public boolean isCreatedBeforeRevocation(PGPSignature signature, PGPPublicKey key) {
+ if (signature.getKeyID() != key.getKeyID()) {
+ throw new IllegalArgumentException("The signature's key ID must be the same as the key's key ID"); //$NON-NLS-1$
+ }
+ Date verifiedRevocationDate = getVerifiedRevocationDate(key);
+ if (verifiedRevocationDate != null) {
+ long signatureCreationTime = signature.getCreationTime().getTime();
+ if (signatureCreationTime >= verifiedRevocationDate.getTime()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the hexadecimal representation of the key's
+ * {@link PGPPublicKey#getFingerprint() fingerprint}.
+ *
+ * @param key the key for which to get the hexadecimal fingerprint.
+ *
+ * @return the hexadecimal representation of the key's fingerprint.
+ */
+ public static String toHexFingerprint(PGPPublicKey key) {
+ return Hex.toHexString(key.getFingerprint());
+ }
+
+ /**
+ * Returns the hexadecimal representation of the given bytes.
+ *
+ * @param bytes the bytes to convert to a hexadecimal representation.
+ * @return the hexadecimal representation of the given bytes.
+ */
+ public static String toHex(byte[] bytes) {
+ return Hex.toHexString(bytes);
+ }
+
+ /**
+ * Returns the hexadecimal representation of the given long value, typically a
+ * key ID, padded with leading zeros to a length of 16.
+ *
+ * @param keyID the long value, typically a key ID, to convert to a hexadecimal
+ * representation.
+ * @return the hexadecimal representation of the given long value, padded with
+ * leading zeros.
+ */
+ public static String toHex(long keyID) {
+ return String.format("%1$016x", keyID); //$NON-NLS-1$
+ }
+
+ /**
+ * If the signature's {@link PGPSignature#getCreationTime() creation time} is
+ * before the key's {@link PGPPublicKey#getCreationTime() creation time}, this
+ * returns a negative value equal to the number of milliseconds that the
+ * signature was created before the key was created. If the key has a
+ * {@link PGPPublicKey#getValidSeconds() validity period}, i.e., if the key
+ * expires, and the signature's creation time is after the key's expiration,
+ * returns a positive value equal to the number of milliseconds that the
+ * signature was created after the key's expiration. Otherwise, the signature
+ * was created during the period of time that the key was valid and this returns
+ * <code>0</code>.
+ *
+ * @param signature the signature to test.
+ * @param key the corresponding key of this signature against which to
+ * test.
+ * @return a negative value representing the number of milliseconds the
+ * signature was created before the key was created, a positive value
+ * representing the number of milliseconds the signature as created
+ * after the key expired, or <code>0</code> if the signature was created
+ * during the valid period of the key.
+ * @throws IllegalArgumentException if the signature's
+ * {@link PGPSignature#getKeyID() key} is not
+ * the same as the key's
+ * {@link PGPPublicKey#getKeyID() key ID}
+ */
+ public static long compareSignatureTimeToKeyValidityTime(PGPSignature signature, PGPPublicKey key) {
+ if (signature.getKeyID() != key.getKeyID()) {
+ throw new IllegalArgumentException("The signature's key ID must be the same as the key's key ID"); //$NON-NLS-1$
+ }
+ long keyCreationTime = key.getCreationTime().getTime();
+ long signatureCreationTime = signature.getCreationTime().getTime();
+ long delta = signatureCreationTime - keyCreationTime;
+ if (delta < 0) {
+ return delta;
+ }
+ long validSeconds = key.getValidSeconds();
+ if (validSeconds != 0) {
+ delta = signatureCreationTime - (keyCreationTime + validSeconds * 1000);
+ if (delta > 0) {
+ return delta;
+ }
+ }
+ return 0;
+ }
+}

Back to the top