diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java')
-rw-r--r-- | bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java new file mode 100644 index 000000000..af03ea893 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedContentImpl.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation 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: IBM Corporation - initial API and implementation + ******************************************************************************/ +package org.eclipse.osgi.internal.signedcontent; + +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.*; +import java.util.*; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile; +import org.eclipse.osgi.signedcontent.*; +import org.eclipse.osgi.util.NLS; + +public class SignedContentImpl implements SignedContent { + final static SignerInfo[] EMPTY_SIGNERINFO = new SignerInfo[0]; + // the content which is signed + volatile SignedBundleFile content; // TODO can this be more general? + // the content entry md results used for entry content verification + // keyed by entry path -> {SignerInfo[] infos, byte[][] results)} + private final Map<String, Object> contentMDResults; + private final SignerInfo[] signerInfos; + // map of tsa singers keyed by SignerInfo -> {tsa_SignerInfo, signingTime} + private Map<SignerInfo, Object[]> tsaSignerInfos; + volatile private boolean checkedValid = false; + + public SignedContentImpl(SignerInfo[] signerInfos, Map<String, Object> contentMDResults) { + this.signerInfos = signerInfos == null ? EMPTY_SIGNERINFO : signerInfos; + this.contentMDResults = contentMDResults; + } + + public SignedContentEntry[] getSignedEntries() { + if (contentMDResults == null) + return new SignedContentEntry[0]; + List<SignedContentEntry> results = new ArrayList<SignedContentEntry>(contentMDResults.size()); + for (Map.Entry<String, Object> entry : contentMDResults.entrySet()) { + String entryName = entry.getKey(); + Object[] mdResult = (Object[]) entry.getValue(); + results.add(new SignedContentEntryImpl(entryName, (SignerInfo[]) mdResult[0])); + } + return results.toArray(new SignedContentEntry[results.size()]); + } + + public SignedContentEntry getSignedEntry(String name) { + if (contentMDResults == null) + return null; + Object[] mdResult = (Object[]) contentMDResults.get(name); + return mdResult == null ? null : new SignedContentEntryImpl(name, (SignerInfo[]) mdResult[0]); + } + + public SignerInfo[] getSignerInfos() { + return signerInfos; + } + + public Date getSigningTime(SignerInfo signerInfo) { + if (tsaSignerInfos == null) + return null; + Object[] tsaInfo = tsaSignerInfos.get(signerInfo); + return tsaInfo == null ? null : (Date) tsaInfo[1]; + } + + public SignerInfo getTSASignerInfo(SignerInfo signerInfo) { + if (tsaSignerInfos == null) + return null; + Object[] tsaInfo = tsaSignerInfos.get(signerInfo); + return tsaInfo == null ? null : (SignerInfo) tsaInfo[0]; + } + + public boolean isSigned() { + return signerInfos.length > 0; + } + + public void checkValidity(SignerInfo signer) throws CertificateExpiredException, CertificateNotYetValidException { + Date signingTime = getSigningTime(signer); + if (checkedValid) + return; + Certificate[] certs = signer.getCertificateChain(); + for (int i = 0; i < certs.length; i++) { + if (!(certs[i] instanceof X509Certificate)) + continue; + if (signingTime == null) + ((X509Certificate) certs[i]).checkValidity(); + else + ((X509Certificate) certs[i]).checkValidity(signingTime); + } + checkedValid = true; + } + + void setContent(SignedBundleFile content) { + this.content = content; + } + + void setTSASignerInfos(Map<SignerInfo, Object[]> tsaSignerInfos) { + this.tsaSignerInfos = tsaSignerInfos; + } + + void addTSASignerInfo(SignerInfo baseInfo, SignerInfo tsaSignerInfo, Date signingTime) { + // sanity check to make sure the baseInfo is here + if (!containsInfo(baseInfo)) + throw new IllegalArgumentException("The baseInfo is not found"); //$NON-NLS-1$ + if (tsaSignerInfos == null) + tsaSignerInfos = new HashMap<SignerInfo, Object[]>(signerInfos.length); + tsaSignerInfos.put(baseInfo, new Object[] {tsaSignerInfo, signingTime}); + } + + Map<String, Object> getContentMDResults() { + return contentMDResults; + } + + private boolean containsInfo(SignerInfo signerInfo) { + for (int i = 0; i < signerInfos.length; i++) + if (signerInfo == signerInfos[i]) + return true; + return false; + } + + InputStream getDigestInputStream(BundleEntry nestedEntry) throws IOException { + if (contentMDResults == null) + return nestedEntry.getInputStream(); + Object[] mdResult = (Object[]) contentMDResults.get(nestedEntry.getName()); + if (mdResult == null) + return null; + return new DigestedInputStream(nestedEntry, content, (SignerInfo[]) mdResult[0], (byte[][]) mdResult[1], nestedEntry.getSize()); + } + + public class SignedContentEntryImpl implements SignedContentEntry { + private final String entryName; + private final SignerInfo[] entrySigners; + + public SignedContentEntryImpl(String entryName, SignerInfo[] entrySigners) { + this.entryName = entryName; + this.entrySigners = entrySigners == null ? EMPTY_SIGNERINFO : entrySigners; + } + + public String getName() { + return entryName; + } + + public SignerInfo[] getSignerInfos() { + return entrySigners; + } + + public boolean isSigned() { + return entrySigners.length > 0; + } + + public void verify() throws IOException, InvalidContentException { + BundleFile currentContent = content; + if (currentContent == null) + throw new InvalidContentException("The content was not set", null); //$NON-NLS-1$ + BundleEntry entry = null; + SecurityException exception = null; + try { + entry = currentContent.getEntry(entryName); + } catch (SecurityException e) { + exception = e; + } + if (entry == null) + throw new InvalidContentException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, entryName, currentContent.getBaseFile().toString()), exception); + entry.getBytes(); + } + } +} |