org.eclipse.osgi_3.7.2.v20120110-1415

ackage org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.util.NLS;

public class SignatureBlockProcessor
  implements SignedContentConstants
{
  private final SignedBundleFile signedBundle;
  private List<SignerInfo> signerInfos = new ArrayList();
  private Map<String, Object> contentMDResults = new HashMap();
  private Map<SignerInfo, Object[]> tsaSignerInfos;
  private final int supportFlags;
  
  public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags)
  {
    signedBundle = signedContent;
    this.supportFlags = supportFlags;
  }
  
  public SignedContentImpl process()
    throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    BundleFile wrappedBundleFile = signedBundle.getWrappedBundleFile();
    BundleEntry be = wrappedBundleFile.getEntry("META-INF/MANIFEST.MF");
    if (be == null) {
      return createUnsignedContent();
    }
    Enumeration<String> en = wrappedBundleFile.getEntryPaths("META-INF/");
    List<String> signers = new ArrayList(2);
    while (en.hasMoreElements())
    {
      String name = (String)en.nextElement();
      if (((name.endsWith(".DSA")) || (name.endsWith(".RSA"))) && (name.indexOf('/') == name.lastIndexOf('/'))) {
        signers.add(name);
      }
    }
    if (signers.size() == 0) {
      return createUnsignedContent();
    }
    byte[] manifestBytes = readIntoArray(be);
    for (Iterator<String> iSigners = signers.iterator(); iSigners.hasNext();) {
      processSigner(wrappedBundleFile, manifestBytes, (String)iSigners.next());
    }
    SignerInfo[] allSigners = (SignerInfo[])signerInfos.toArray(new SignerInfo[signerInfos.size()]);
    for (Iterator<Map.Entry<String, Object>> iResults = contentMDResults.entrySet().iterator(); iResults.hasNext();)
    {
      Map.Entry<String, Object> entry = (Map.Entry)iResults.next();
      
      List[] value = (List[])entry.getValue();
      SignerInfo[] entrySigners = (SignerInfo[])value[0].toArray(new SignerInfo[value[0].size()]);
      byte[][] entryResults = (byte[][])value[1].toArray(new byte[value[1].size()][]);
      entry.setValue(new Object[] { entrySigners, entryResults });
    }
    SignedContentImpl result = new SignedContentImpl(allSigners, (supportFlags & 0x4) != 0 ? contentMDResults : null);
    result.setContent(signedBundle);
    result.setTSASignerInfos(tsaSignerInfos);
    return result;
  }
  
  private SignedContentImpl createUnsignedContent()
  {
    SignedContentImpl result = new SignedContentImpl(new SignerInfo[0], contentMDResults);
    result.setContent(signedBundle);
    return result;
  }
  
  private void processSigner(BundleFile bf, byte[] manifestBytes, String signer)
    throws IOException, SignatureException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    BundleEntry be = bf.getEntry(signer);
    byte[] pkcs7Bytes = readIntoArray(be);
    int dotIndex = signer.lastIndexOf('.');
    be = bf.getEntry(signer.substring(0, dotIndex) + ".SF");
    byte[] sfBytes = readIntoArray(be);
    
    String baseFile = bf.getBaseFile() != null ? bf.getBaseFile().toString() : null;
    PKCS7Processor processor = new PKCS7Processor(pkcs7Bytes, 0, pkcs7Bytes.length, signer, baseFile);
    
    processor.verifySFSignature(sfBytes, 0, sfBytes.length);
    
    String digAlg = getDigAlgFromSF(sfBytes);
    if (digAlg == null) {
      throw new SignatureException(NLS.bind(SignedContentMessages.SF_File_Parsing_Error, new String[] { bf.toString() }));
    }
    verifyManifestAndSignatureFile(manifestBytes, sfBytes);
    
    SignerInfoImpl signerInfo = new SignerInfoImpl(processor.getCertificates(), null, digAlg);
    if ((supportFlags & 0x4) != 0) {
      populateMDResults(manifestBytes, signerInfo);
    }
    signerInfos.add(signerInfo);
    
    Certificate[] tsaCerts = processor.getTSACertificates();
    Date signingTime = processor.getSigningTime();
    if ((tsaCerts != null) && (signingTime != null))
    {
      SignerInfoImpl tsaSignerInfo = new SignerInfoImpl(tsaCerts, null, digAlg);
      if (tsaSignerInfos == null) {
        tsaSignerInfos = new HashMap(2);
      }
      tsaSignerInfos.put(signerInfo, new Object[] { tsaSignerInfo, signingTime });
    }
  }
  
  private void verifyManifestAndSignatureFile(byte[] manifestBytes, byte[] sfBytes)
    throws SignatureException
  {
    String sf = new String(sfBytes);
    sf = stripContinuations(sf);
    
    int off = sf.indexOf("-Digest-Manifest: ");
    if (off != -1)
    {
      int start = sf.lastIndexOf('\n', off);
      String manifestDigest = null;
      if (start != -1)
      {
        String digestName = sf.substring(start + 1, off);
        if (digestName.equalsIgnoreCase("MD5")) {
          manifestDigest = calculateDigest(getMessageDigest("MD5"), manifestBytes);
        } else if (digestName.equalsIgnoreCase("SHA1")) {
          manifestDigest = calculateDigest(getMessageDigest("SHA1"), manifestBytes);
        }
        off += digestManifestSearchLen;
        
        int nIndex = sf.indexOf('\n', off);
        String digestValue = sf.substring(off, nIndex - 1);
        if (!digestValue.equals(manifestDigest))
        {
          SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] { signedBundle.getBaseFile().toString() }));
          SignedBundleHook.log(se.getMessage(), 4, se);
          throw se;
        }
      }
    }
  }
  
  private void populateMDResults(byte[] mfBuf, SignerInfo signerInfo)
    throws NoSuchAlgorithmException
  {
    String mfStr = new String(mfBuf);
    
    int entryStartOffset = mfStr.indexOf("\nName: ");
    int length = mfStr.length();
    while ((entryStartOffset != -1) && (entryStartOffset < length))
    {
      int entryEndOffset = mfStr.indexOf("\nName: ", entryStartOffset + 1);
      if (entryEndOffset == -1) {
        entryEndOffset = mfStr.length();
      }
      String entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
      entryStr = stripContinuations(entryStr);
      
      String entryName = getEntryFileName(entryStr);
      if (entryName != null)
      {
        String aDigestLine = getDigestLine(entryStr, signerInfo.getMessageDigestAlgorithm());
        if (aDigestLine != null)
        {
          String msgDigestAlgorithm = getDigestAlgorithmFromString(aDigestLine);
          if (!msgDigestAlgorithm.equalsIgnoreCase(signerInfo.getMessageDigestAlgorithm())) {
            continue;
          }
          byte[] digestResult = getDigestResultsList(aDigestLine);
          
          List[] mdResult = (List[])contentMDResults.get(entryName);
          if (mdResult == null)
          {
            List[] arrayLists = new ArrayList[2];
            mdResult = arrayLists;
            mdResult[0] = new ArrayList();
            mdResult[1] = new ArrayList();
            contentMDResults.put(entryName, mdResult);
          }
          mdResult[0].add(signerInfo);
          mdResult[1].add(digestResult);
        }
      }
      entryStartOffset = entryEndOffset;
    }
  }
  
  private static byte[] getDigestResultsList(String digestLines)
  {
    byte[] resultsList = (byte[])null;
    if (digestLines != null)
    {
      String sDigestLine = digestLines;
      int indexDigest = sDigestLine.indexOf("-Digest: ");
      indexDigest += "-Digest: ".length();
      if (indexDigest >= sDigestLine.length()) {
        resultsList = (byte[])null;
      }
      String sResult = sDigestLine.substring(indexDigest);
      try
      {
        resultsList = Base64.decode(sResult.getBytes());
      }
      catch (Throwable localThrowable)
      {
        resultsList = (byte[])null;
      }
    }
    return resultsList;
  }
  
  private static String getDigestAlgorithmFromString(String digestLines)
    throws NoSuchAlgorithmException
  {
    if (digestLines != null)
    {
      int indexDigest = digestLines.indexOf("-Digest: ");
      String sDigestAlgType = digestLines.substring(0, indexDigest);
      if (sDigestAlgType.equalsIgnoreCase("MD5")) {
        return "MD5";
      }
      if (sDigestAlgType.equalsIgnoreCase("SHA1")) {
        return "SHA1";
      }
      throw new NoSuchAlgorithmException(NLS.bind(SignedContentMessages.Algorithm_Not_Supported, sDigestAlgType));
    }
    return null;
  }
  
  private static String getEntryFileName(String manifestEntry)
  {
    int nameStart = manifestEntry.indexOf("Name: ");
    if (nameStart == -1) {
      return null;
    }
    int nameEnd = manifestEntry.indexOf('\n', nameStart);
    if (nameEnd == -1) {
      return null;
    }
    if (manifestEntry.charAt(nameEnd - 1) == '\r') {
      nameEnd--;
    }
    nameStart += "Name: ".length();
    if (nameStart >= nameEnd) {
      return null;
    }
    return manifestEntry.substring(nameStart, nameEnd);
  }
  
  private static String calculateDigest(MessageDigest digest, byte[] bytes)
  {
    return new String(Base64.encode(digest.digest(bytes)));
  }
  
  static synchronized MessageDigest getMessageDigest(String algorithm)
  {
    try
    {
      return MessageDigest.getInstance(algorithm);
    }
    catch (NoSuchAlgorithmException e)
    {
      SignedBundleHook.log(e.getMessage(), 4, e);
    }
    return null;
  }
  
  private static String getDigAlgFromSF(byte[] SFBuf)
  {
    String mfStr = new String(SFBuf);
    String entryStr = null;
    
    int entryStartOffset = mfStr.indexOf("\nName: ");
    int length = mfStr.length();
    if ((entryStartOffset != -1) && (entryStartOffset < length))
    {
      int entryEndOffset = mfStr.indexOf("\nName: ", entryStartOffset + 1);
      if (entryEndOffset == -1) {
        entryEndOffset = mfStr.length();
      }
      entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
      entryStr = stripContinuations(entryStr);
    }
    if (entryStr != null)
    {
      String digestLine = getDigestLine(entryStr, null);
      
      return getMessageDigestName(digestLine);
    }
    return null;
  }
  
  private static String getDigestLine(String manifestEntry, String desireDigestAlg)
  {
    String result = null;
    
    int indexDigest = manifestEntry.indexOf("-Digest: ");
    if (indexDigest == -1) {
      return null;
    }
    while (indexDigest != -1)
    {
      int indexStart = manifestEntry.lastIndexOf('\n', indexDigest);
      if (indexStart == -1) {
        return null;
      }
      int indexEnd = manifestEntry.indexOf('\n', indexDigest);
      if (indexEnd == -1) {
        return null;
      }
      int indexEndToUse = indexEnd;
      if (manifestEntry.charAt(indexEndToUse - 1) == '\r') {
        indexEndToUse--;
      }
      int indexStartToUse = indexStart + 1;
      if (indexStartToUse >= indexEndToUse) {
        return null;
      }
      String digestLine = manifestEntry.substring(indexStartToUse, indexEndToUse);
      String digAlg = getMessageDigestName(digestLine);
      if ((desireDigestAlg != null) && 
        (desireDigestAlg.equalsIgnoreCase(digAlg))) {
        return digestLine;
      }
      result = digestLine;
      
      indexDigest = manifestEntry.indexOf("-Digest: ", indexEnd);
    }
    return result;
  }
  
  private static String getMessageDigestName(String digLine)
  {
    String rtvValue = null;
    if (digLine != null)
    {
      int indexDigest = digLine.indexOf("-Digest: ");
      if (indexDigest != -1) {
        rtvValue = digLine.substring(0, indexDigest);
      }
    }
    return rtvValue;
  }
  
  private static String stripContinuations(String entry)
  {
    if (entry.indexOf("\n ") < 0) {
      return entry;
    }
    StringBuffer buffer = new StringBuffer(entry.length());
    int cont = entry.indexOf("\n ");
    int start = 0;
    while (cont >= 0)
    {
      buffer.append(entry.substring(start, cont - 1));
      start = cont + 2;
      cont = cont + 2 < entry.length() ? entry.indexOf("\n ", cont + 2) : -1;
    }
    if (start < entry.length()) {
      buffer.append(entry.substring(start));
    }
    return buffer.toString();
  }
  
  private static byte[] readIntoArray(BundleEntry be)
    throws IOException
  {
    int size = (int)be.getSize();
    InputStream is = be.getInputStream();
    try
    {
      byte[] b = new byte[size];
      int rc = readFully(is, b);
      if (rc != size) {
        throw new IOException("Couldn't read all of " + be.getName() + ": " + rc + " != " + size);
      }
      return b;
    }
    finally
    {
      try
      {
        is.close();
      }
      catch (IOException localIOException2) {}
    }
  }
  
  private static int readFully(InputStream is, byte[] b)
    throws IOException
  {
    int count = b.length;
    int offset = 0;
    int rc;
    while ((rc = is.read(b, offset, count)) > 0)
    {
      int rc;
      count -= rc;
      offset += rc;
    }
    return offset;
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignatureBlockProcessor
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;

class SignedBundleFile$SignedBundleEntry
  extends BundleEntry
{
  BundleEntry nestedEntry;
  final SignedBundleFile this$0;
  
  SignedBundleFile$SignedBundleEntry(SignedBundleFile paramSignedBundleFile, BundleEntry nestedEntry)
  {
    this.nestedEntry = nestedEntry;
  }
  
  public InputStream getInputStream()
    throws IOException
  {
    InputStream in = this$0.signedContent.getDigestInputStream(nestedEntry);
    if (in == null) {
      throw new SecurityException("Corrupted file: the digest does not exist for the file " + nestedEntry.getName());
    }
    return in;
  }
  
  public long getSize()
  {
    return nestedEntry.getSize();
  }
  
  public String getName()
  {
    return nestedEntry.getName();
  }
  
  public long getTime()
  {
    return nestedEntry.getTime();
  }
  
  public URL getLocalURL()
  {
    return nestedEntry.getLocalURL();
  }
  
  public URL getFileURL()
  {
    return nestedEntry.getFileURL();
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignedBundleFile.SignedBundleEntry
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.util.Date;
import java.util.Enumeration;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.service.security.TrustEngine;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.util.NLS;

public class SignedBundleFile
  extends BundleFile
  implements SignedContentConstants, SignedContent
{
  private BundleFile wrappedBundleFile;
  SignedContentImpl signedContent;
  private final int supportFlags;
  
  SignedBundleFile(SignedContentImpl signedContent, int supportFlags)
  {
    this.signedContent = signedContent;
    this.supportFlags = supportFlags;
  }
  
  void setBundleFile(BundleFile bundleFile)
    throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    wrappedBundleFile = bundleFile;
    if (signedContent == null)
    {
      SignatureBlockProcessor signatureProcessor = new SignatureBlockProcessor(this, supportFlags);
      signedContent = signatureProcessor.process();
      if (signedContent != null) {
        determineTrust(signedContent, supportFlags);
      }
    }
  }
  
  static void determineTrust(SignedContentImpl trustedContent, int supportFlags)
  {
    TrustEngine[] engines = (TrustEngine[])null;
    SignerInfo[] signers = trustedContent.getSignerInfos();
    for (int i = 0; i < signers.length; i++) {
      if (signers[i].getTrustAnchor() == null)
      {
        if (engines == null) {
          engines = SignedBundleHook.getTrustEngines();
        }
        Certificate[] signerCerts = signers[i].getCertificateChain();
        ((SignerInfoImpl)signers[i]).setTrustAnchor(findTrustAnchor(signerCerts, engines, supportFlags));
        
        SignerInfo tsaSignerInfo = trustedContent.getTSASignerInfo(signers[i]);
        if (tsaSignerInfo != null)
        {
          Certificate[] tsaCerts = tsaSignerInfo.getCertificateChain();
          ((SignerInfoImpl)tsaSignerInfo).setTrustAnchor(findTrustAnchor(tsaCerts, engines, supportFlags));
        }
      }
    }
  }
  
  private static Certificate findTrustAnchor(Certificate[] certs, TrustEngine[] engines, int supportFlags)
  {
    if ((supportFlags & 0x2) == 0) {
      return (certs != null) && (certs.length > 0) ? certs[(certs.length - 1)] : null;
    }
    for (int i = 0; i < engines.length; i++) {
      try
      {
        Certificate anchor = engines[i].findTrustAnchor(certs);
        if (anchor != null) {
          return anchor;
        }
      }
      catch (IOException e)
      {
        SignedBundleHook.log("TrustEngine failure: " + engines[i].getName(), 2, e);
      }
    }
    return null;
  }
  
  public File getFile(String path, boolean nativeCode)
  {
    return wrappedBundleFile.getFile(path, nativeCode);
  }
  
  public BundleEntry getEntry(String path)
  {
    if ((path.length() > 0) && (path.charAt(0) == '/')) {
      path = path.substring(1);
    }
    BundleEntry be = wrappedBundleFile.getEntry(path);
    if (((supportFlags & 0x4) == 0) || (signedContent == null)) {
      return be;
    }
    if (path.startsWith("META-INF/"))
    {
      int lastSlash = path.lastIndexOf('/');
      if (lastSlash == "META-INF/".length() - 1)
      {
        if ((path.equals("META-INF/MANIFEST.MF")) || (path.endsWith(".DSA")) || (path.endsWith(".RSA")) || (path.endsWith(".SF")) || (path.indexOf("SIG-") == "META-INF/".length())) {
          return be;
        }
        SignedContentEntry signedEntry = signedContent.getSignedEntry(path);
        if (signedEntry == null) {
          return be;
        }
      }
    }
    if (be == null)
    {
      SignedContentEntry signedEntry = signedContent.getSignedEntry(path);
      if (signedEntry != null) {
        throw new SecurityException(NLS.bind(SignedContentMessages.file_is_removed_from_jar, path, getBaseFile().toString()));
      }
      return null;
    }
    return new SignedBundleEntry(be);
  }
  
  public Enumeration<String> getEntryPaths(String path)
  {
    return wrappedBundleFile.getEntryPaths(path);
  }
  
  public void close()
    throws IOException
  {
    wrappedBundleFile.close();
  }
  
  public void open()
    throws IOException
  {
    wrappedBundleFile.open();
  }
  
  public boolean containsDir(String dir)
  {
    return wrappedBundleFile.containsDir(dir);
  }
  
  public File getBaseFile()
  {
    return wrappedBundleFile.getBaseFile();
  }
  
  class SignedBundleEntry
    extends BundleEntry
  {
    BundleEntry nestedEntry;
    
    SignedBundleEntry(BundleEntry nestedEntry)
    {
      this.nestedEntry = nestedEntry;
    }
    
    public InputStream getInputStream()
      throws IOException
    {
      InputStream in = signedContent.getDigestInputStream(nestedEntry);
      if (in == null) {
        throw new SecurityException("Corrupted file: the digest does not exist for the file " + nestedEntry.getName());
      }
      return in;
    }
    
    public long getSize()
    {
      return nestedEntry.getSize();
    }
    
    public String getName()
    {
      return nestedEntry.getName();
    }
    
    public long getTime()
    {
      return nestedEntry.getTime();
    }
    
    public URL getLocalURL()
    {
      return nestedEntry.getLocalURL();
    }
    
    public URL getFileURL()
    {
      return nestedEntry.getFileURL();
    }
  }
  
  BundleFile getWrappedBundleFile()
  {
    return wrappedBundleFile;
  }
  
  SignedContentImpl getSignedContent()
  {
    return signedContent;
  }
  
  public SignedContentEntry[] getSignedEntries()
  {
    return signedContent == null ? null : signedContent.getSignedEntries();
  }
  
  public SignedContentEntry getSignedEntry(String name)
  {
    return signedContent == null ? null : signedContent.getSignedEntry(name);
  }
  
  public SignerInfo[] getSignerInfos()
  {
    return signedContent == null ? null : signedContent.getSignerInfos();
  }
  
  public Date getSigningTime(SignerInfo signerInfo)
  {
    return signedContent == null ? null : signedContent.getSigningTime(signerInfo);
  }
  
  public SignerInfo getTSASignerInfo(SignerInfo signerInfo)
  {
    return signedContent == null ? null : signedContent.getTSASignerInfo(signerInfo);
  }
  
  public boolean isSigned()
  {
    return signedContent == null ? false : signedContent.isSigned();
  }
  
  public void checkValidity(SignerInfo signerInfo)
    throws CertificateExpiredException, CertificateNotYetValidException
  {
    if (signedContent != null) {
      signedContent.checkValidity(signerInfo);
    }
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignedBundleFile
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.security.PrivilegedExceptionAction;
import org.eclipse.osgi.baseadaptor.BaseData;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.signedcontent.SignedContent;

class SignedBundleHook$1
  implements PrivilegedExceptionAction<SignedContent>
{
  final SignedBundleHook this$0;
  
  SignedBundleHook$1(SignedBundleHook paramSignedBundleHook, BundleData paramBundleData) {}
  
  public SignedContent run()
    throws Exception
  {
    return this$0.getSignedContent(((BaseData)val$data).getBundleFile().getBaseFile());
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignedBundleHook.1
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse.osgi.internal.signedcontent;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import org.eclipse.osgi.baseadaptor.BaseAdaptor;
import org.eclipse.osgi.baseadaptor.BaseData;
import org.eclipse.osgi.baseadaptor.HookConfigurator;
import org.eclipse.osgi.baseadaptor.HookRegistry;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.baseadaptor.bundlefile.DirBundleFile;
import org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleFile;
import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.FilterImpl;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.provisional.service.security.AuthorizationEngine;
import org.eclipse.osgi.internal.provisional.verifier.CertificateVerifierFactory;
import org.eclipse.osgi.internal.service.security.DefaultAuthorizationEngine;
import org.eclipse.osgi.internal.service.security.KeyStoreTrustEngine;
import org.eclipse.osgi.service.security.TrustEngine;
import org.eclipse.osgi.signedcontent.SignedContent;
import org.eclipse.osgi.signedcontent.SignedContentFactory;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;

public class SignedBundleHook
  implements AdaptorHook, BundleFileWrapperFactoryHook, HookConfigurator, SignedContentFactory
{
  static final int VERIFY_CERTIFICATE = 1;
  static final int VERIFY_TRUST = 2;
  static final int VERIFY_RUNTIME = 4;
  static final int VERIFY_AUTHORITY = 8;
  static final int VERIFY_ALL = 15;
  private static String SUPPORT_CERTIFICATE = "certificate";
  private static String SUPPORT_TRUST = "trust";
  private static String SUPPORT_RUNTIME = "runtime";
  private static String SUPPORT_AUTHORITY = "authority";
  private static String SUPPORT_ALL = "all";
  private static String SUPPORT_TRUE = "true";
  private static String CACERTS_PATH = System.getProperty("java.home") + File.separatorChar + "lib" + File.separatorChar + "security" + File.separatorChar + "cacerts";
  private static String CACERTS_TYPE = "JKS";
  private static ServiceTracker<TrustEngine, TrustEngine> trustEngineTracker;
  private static BaseAdaptor ADAPTOR;
  private static String SIGNED_BUNDLE_SUPPORT = "osgi.support.signature.verify";
  private static String SIGNED_CONTENT_SUPPORT = "osgi.signedcontent.support";
  private static String OSGI_KEYSTORE = "osgi.framework.keystore";
  private static int supportSignedBundles;
  private TrustEngineListener trustEngineListener;
  private BundleInstallListener installListener;
  private ServiceRegistration<?> signedContentFactoryReg;
  private ServiceRegistration<?> systemTrustEngineReg;
  private ServiceRegistration<?> defaultAuthEngineReg;
  private List<ServiceRegistration<?>> osgiTrustEngineReg;
  private ServiceRegistration<?> legacyFactoryReg;
  
  public void initialize(BaseAdaptor adaptor)
  {
    ADAPTOR = adaptor;
  }
  
  public void frameworkStart(BundleContext context)
    throws BundleException
  {
    if ((supportSignedBundles & 0x8) != 0)
    {
      installListener = new BundleInstallListener();
      context.addBundleListener(installListener);
      
      Dictionary<String, Object> properties = new Hashtable(7);
      properties.put("service.ranking", new Integer(Integer.MIN_VALUE));
      properties.put("osgi.signedcontent.authorization.engine", SignedContentConstants.DEFAULT_AUTHORIZATION_ENGINE);
      defaultAuthEngineReg = context.registerService(AuthorizationEngine.class.getName(), new DefaultAuthorizationEngine(context, ADAPTOR.getState()), properties);
    }
    Dictionary<String, Object> trustEngineProps = new Hashtable(7);
    trustEngineProps.put("service.ranking", new Integer(Integer.MIN_VALUE));
    trustEngineProps.put("osgi.signedcontent.trust.engine", SignedContentConstants.DEFAULT_TRUST_ENGINE);
    KeyStoreTrustEngine systemTrustEngine = new KeyStoreTrustEngine(CACERTS_PATH, CACERTS_TYPE, null, "System");
    systemTrustEngineReg = context.registerService(TrustEngine.class.getName(), systemTrustEngine, trustEngineProps);
    String osgiTrustPath = context.getProperty(OSGI_KEYSTORE);
    if (osgiTrustPath != null)
    {
      try
      {
        URL url = new URL(osgiTrustPath);
        if (!"file".equals(url.getProtocol())) {
          break label538;
        }
        trustEngineProps.put("osgi.signedcontent.trust.engine", OSGI_KEYSTORE);
        String path = url.getPath();
        osgiTrustEngineReg = new ArrayList(1);
        osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(path, CACERTS_TYPE, null, OSGI_KEYSTORE), trustEngineProps));
      }
      catch (MalformedURLException e)
      {
        log("Invalid setting for " + OSGI_KEYSTORE, 2, e);
      }
    }
    else
    {
      String osgiTrustRepoPaths = context.getProperty("org.osgi.framework.trust.repositories");
      if (osgiTrustRepoPaths != null)
      {
        trustEngineProps.put("osgi.signedcontent.trust.engine", "org.osgi.framework.trust.repositories");
        StringTokenizer st = new StringTokenizer(osgiTrustRepoPaths, File.pathSeparator);
        osgiTrustEngineReg = new ArrayList(1);
        while (st.hasMoreTokens())
        {
          String trustRepoPath = st.nextToken();
          osgiTrustEngineReg.add(context.registerService(TrustEngine.class.getName(), new KeyStoreTrustEngine(trustRepoPath, CACERTS_TYPE, null, OSGI_KEYSTORE), trustEngineProps));
        }
      }
    }
    label538:
    if ((supportSignedBundles & 0x2) != 0) {
      trustEngineListener = new TrustEngineListener(context);
    }
    signedContentFactoryReg = context.registerService(SignedContentFactory.class.getName(), this, null);
    legacyFactoryReg = context.registerService(CertificateVerifierFactory.class.getName(), new LegacyVerifierFactory(this), null);
  }
  
  public void frameworkStop(BundleContext context)
    throws BundleException
  {
    if (legacyFactoryReg != null)
    {
      legacyFactoryReg.unregister();
      legacyFactoryReg = null;
    }
    if (signedContentFactoryReg != null)
    {
      signedContentFactoryReg.unregister();
      signedContentFactoryReg = null;
    }
    if (systemTrustEngineReg != null)
    {
      systemTrustEngineReg.unregister();
      systemTrustEngineReg = null;
    }
    if (osgiTrustEngineReg != null)
    {
      for (Iterator<ServiceRegistration<?>> it = osgiTrustEngineReg.iterator(); it.hasNext();) {
        ((ServiceRegistration)it.next()).unregister();
      }
      osgiTrustEngineReg = null;
    }
    if (defaultAuthEngineReg != null)
    {
      defaultAuthEngineReg.unregister();
      defaultAuthEngineReg = null;
    }
    if (trustEngineListener != null)
    {
      trustEngineListener.stopTrustEngineListener();
      trustEngineListener = null;
    }
    if (installListener != null)
    {
      context.removeBundleListener(installListener);
      installListener = null;
    }
    if (trustEngineTracker != null)
    {
      trustEngineTracker.close();
      trustEngineTracker = null;
    }
  }
  
  public void frameworkStopping(BundleContext context) {}
  
  public void addProperties(Properties properties) {}
  
  public URLConnection mapLocationToURLConnection(String location)
    throws IOException
  {
    return null;
  }
  
  public void handleRuntimeError(Throwable error) {}
  
  public FrameworkLog createFrameworkLog()
  {
    return null;
  }
  
  public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base)
  {
    try
    {
      if (bundleFile != null)
      {
        SignedStorageHook hook = (SignedStorageHook)data.getStorageHook(SignedStorageHook.KEY);
        SignedBundleFile signedBaseFile;
        if ((base) && (hook != null))
        {
          SignedBundleFile signedBaseFile = new SignedBundleFile(signedContent, supportSignedBundles);
          if (signedContent == null)
          {
            signedBaseFile.setBundleFile(bundleFile);
            SignedContentImpl signedContent = signedBaseFile.getSignedContent();
            signedContent = ((signedContent != null) && (signedContent.isSigned()) ? signedContent : null);
          }
        }
        else
        {
          signedBaseFile = new SignedBundleFile(null, supportSignedBundles);
        }
        signedBaseFile.setBundleFile(bundleFile);
        SignedContentImpl signedContent = signedBaseFile.getSignedContent();
        if ((signedContent != null) && (signedContent.isSigned()))
        {
          signedContent.setContent(signedBaseFile);
          bundleFile = signedBaseFile;
        }
      }
    }
    catch (IOException e)
    {
      log("Bad bundle file: " + bundleFile.getBaseFile(), 2, e);
    }
    catch (GeneralSecurityException e)
    {
      log("Bad bundle file: " + bundleFile.getBaseFile(), 2, e);
    }
    return bundleFile;
  }
  
  public void addHooks(HookRegistry hookRegistry)
  {
    hookRegistry.addAdaptorHook(this);
    String[] support = ManifestElement.getArrayFromList(FrameworkProperties.getProperty(SIGNED_CONTENT_SUPPORT, FrameworkProperties.getProperty(SIGNED_BUNDLE_SUPPORT)), ",");
    for (int i = 0; i < support.length; i++) {
      if (SUPPORT_CERTIFICATE.equals(support[i])) {
        supportSignedBundles |= 0x1;
      } else if (SUPPORT_TRUST.equals(support[i])) {
        supportSignedBundles |= 0x3;
      } else if (SUPPORT_RUNTIME.equals(support[i])) {
        supportSignedBundles |= 0x5;
      } else if (SUPPORT_AUTHORITY.equals(support[i])) {
        supportSignedBundles |= 0xB;
      } else if ((SUPPORT_TRUE.equals(support[i])) || (SUPPORT_ALL.equals(support[i]))) {
        supportSignedBundles |= 0xF;
      }
    }
    if ((supportSignedBundles & 0x1) != 0)
    {
      hookRegistry.addStorageHook(new SignedStorageHook());
      hookRegistry.addBundleFileWrapperFactoryHook(this);
    }
  }
  
  public SignedContent getSignedContent(File content)
    throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException
  {
    if (content == null) {
      throw new IllegalArgumentException("null content");
    }
    BundleFile contentBundleFile;
    BundleFile contentBundleFile;
    if (content.isDirectory()) {
      contentBundleFile = new DirBundleFile(content);
    } else {
      contentBundleFile = new ZipBundleFile(content, null);
    }
    SignedBundleFile result = new SignedBundleFile(null, 15);
    try
    {
      result.setBundleFile(contentBundleFile);
    }
    catch (InvalidKeyException e)
    {
      throw ((InvalidKeyException)new InvalidKeyException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e));
    }
    catch (SignatureException e)
    {
      throw ((SignatureException)new SignatureException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e));
    }
    catch (CertificateException e)
    {
      throw ((CertificateException)new CertificateException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e));
    }
    catch (NoSuchAlgorithmException e)
    {
      throw ((NoSuchAlgorithmException)new NoSuchAlgorithmException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e));
    }
    catch (NoSuchProviderException e)
    {
      throw ((NoSuchProviderException)new NoSuchProviderException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e));
    }
    return new SignedContentFile(result.getSignedContent());
  }
  
  public SignedContent getSignedContent(Bundle bundle)
    throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException, IllegalArgumentException
  {
    final BundleData data = ((AbstractBundle)bundle).getBundleData();
    if (!(data instanceof BaseData)) {
      throw new IllegalArgumentException("Invalid bundle object.  No BaseData found.");
    }
    SignedStorageHook hook = (SignedStorageHook)((BaseData)data).getStorageHook(SignedStorageHook.KEY);
    SignedContent result = hook != null ? signedContent : null;
    if (result != null) {
      return result;
    }
    if (System.getSecurityManager() == null) {
      return getSignedContent(((BaseData)data).getBundleFile().getBaseFile());
    }
    try
    {
      (SignedContent)AccessController.doPrivileged(new PrivilegedExceptionAction()
      {
        public SignedContent run()
          throws Exception
        {
          return getSignedContent(((BaseData)data).getBundleFile().getBaseFile());
        }
      });
    }
    catch (PrivilegedActionException e)
    {
      if ((e.getException() instanceof IOException)) {
        throw ((IOException)e.getException());
      }
      if ((e.getException() instanceof InvalidKeyException)) {
        throw ((InvalidKeyException)e.getException());
      }
      if ((e.getException() instanceof SignatureException)) {
        throw ((SignatureException)e.getException());
      }
      if ((e.getException() instanceof CertificateException)) {
        throw ((CertificateException)e.getException());
      }
      if ((e.getException() instanceof NoSuchAlgorithmException)) {
        throw ((NoSuchAlgorithmException)e.getException());
      }
      if ((e.getException() instanceof NoSuchProviderException)) {
        throw ((NoSuchProviderException)e.getException());
      }
      throw new RuntimeException("Unknown error.", e.getException());
    }
  }
  
  public static void log(String msg, int severity, Throwable t)
  {
    if (ADAPTOR == null)
    {
      System.err.println(msg);
      t.printStackTrace();
      return;
    }
    FrameworkLogEntry entry = new FrameworkLogEntry("org.eclipse.osgi", severity, 0, msg, 0, t, null);
    ADAPTOR.getFrameworkLog().log(entry);
  }
  
  static BundleContext getContext()
  {
    if (ADAPTOR == null) {
      return null;
    }
    return ADAPTOR.getContext();
  }
  
  static TrustEngine[] getTrustEngines()
  {
    BundleContext context = getContext();
    if (context == null) {
      return new TrustEngine[0];
    }
    if (trustEngineTracker == null)
    {
      String trustEngineProp = FrameworkProperties.getProperty("osgi.signedcontent.trust.engine");
      Filter filter = null;
      if (trustEngineProp != null) {
        try
        {
          filter = FilterImpl.newInstance("(&(objectClass=" + TrustEngine.class.getName() + ")(" + "osgi.signedcontent.trust.engine" + "=" + trustEngineProp + "))");
        }
        catch (InvalidSyntaxException e)
        {
          log("Invalid trust engine filter", 2, e);
        }
      }
      if (filter != null) {
        trustEngineTracker = new ServiceTracker(context, filter, null);
      } else {
        trustEngineTracker = new ServiceTracker(context, TrustEngine.class.getName(), null);
      }
      trustEngineTracker.open();
    }
    Object[] services = trustEngineTracker.getServices();
    if (services != null)
    {
      TrustEngine[] engines = new TrustEngine[services.length];
      System.arraycopy(services, 0, engines, 0, services.length);
      return engines;
    }
    return new TrustEngine[0];
  }
}

/* Location:
 * Qualified Name:     org.eclipse.osgi.internal.signedcontent.SignedBundleHook
 * Java Class Version: 1.4 (48.0)
 * JD-Core Version:    0.7.1
 */
package org.eclipse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd