1 9 package org.eclipse.osgi.internal.verifier; 10 11 import java.io.*; 12 import java.security.cert.*; 13 import java.util.*; 14 import org.eclipse.osgi.baseadaptor.BaseData; 15 import org.eclipse.osgi.baseadaptor.hooks.StorageHook; 16 import org.eclipse.osgi.framework.util.KeyedElement; 17 import org.eclipse.osgi.internal.provisional.verifier.CertificateChain; 18 import org.osgi.framework.Bundle; 19 import org.osgi.framework.BundleException; 20 21 public class SignedStorageHook implements StorageHook { 22 static final String KEY = SignedStorageHook.class.getName(); 23 static final int HASHCODE = KEY.hashCode(); 24 private static final int STORAGE_VERSION = 2; 25 private static ArrayList saveChainCache = new ArrayList(5); 26 private static long firstIDSaved = -1; 27 private static long lastIDSaved = -1; 28 private static ArrayList loadChainCache = new ArrayList(5); 29 private static long lastIDLoaded; 30 31 private BaseData bundledata; 32 SignedBundleFile signedBundleFile; 33 34 public int getStorageVersion() { 35 return STORAGE_VERSION; 36 } 37 38 public StorageHook create(BaseData bundledata) throws BundleException { 39 SignedStorageHook hook = new SignedStorageHook(); 40 hook.bundledata = bundledata; 41 return hook; 42 } 43 44 public void initialize(Dictionary manifest) throws BundleException { 45 } 47 48 public StorageHook load(BaseData target, DataInputStream is) throws IOException { 49 if (lastIDLoaded > target.getBundleID()) 50 loadChainCache.clear(); 51 lastIDLoaded = target.getBundleID(); 52 SignedStorageHook hook = new SignedStorageHook(); 53 hook.bundledata = target; 54 boolean signed = is.readBoolean(); 55 if (!signed) 56 return hook; 57 int numChains = is.readInt(); 58 CertificateChain[] chains = new CertificateChain[numChains]; 59 for (int i = 0; i < numChains; i++) { 60 int chainIdx = is.readInt(); 61 if (chainIdx >= 0) { 62 chains[i] = (CertificateChain) loadChainCache.get(chainIdx); 63 if (chains[i] == null) 64 throw new IOException("Invalid chain cache."); continue; 66 } 67 String chain = is.readUTF(); 68 69 boolean trusted = is.readBoolean(); 70 int numCerts = is.readInt(); 71 byte[][] certsBytes = new byte[numCerts][]; 72 for (int j = 0; j < certsBytes.length; j++) { 73 int numBytes = is.readInt(); 74 certsBytes[j] = new byte[numBytes]; 75 is.readFully(certsBytes[j]); 76 } 77 long signingTime = is.readLong(); 78 try { 79 chains[i] = new PKCS7Processor(chain, trusted, certsBytes, signingTime); 80 } catch (CertificateException e) { 81 throw new IOException(e.getMessage()); 82 } 83 loadChainCache.add(chains[i]); 84 } 85 int numEntries = is.readInt(); 86 Hashtable digests = null; 87 Hashtable results = null; 88 if (numEntries >= 0) { 89 digests = new Hashtable(numEntries); 90 results = new Hashtable(numEntries); 91 for (int i = 0; i < numEntries; i++) { 92 String entry = is.readUTF(); 93 String md; 94 byte[] result; 95 if (is.readInt() == 0) 96 md = JarVerifierConstant.MD5_STR; 97 else 98 md = JarVerifierConstant.SHA1_STR; 99 result = new byte[is.readInt()]; 100 is.readFully(result); 101 digests.put(entry, md); 102 results.put(entry, result); 103 } 104 } 105 String md5Result = null; 106 String shaResult = null; 107 if (is.readBoolean()) 108 md5Result = is.readUTF(); 109 if (is.readBoolean()) 110 shaResult = is.readUTF(); 111 hook.signedBundleFile = new SignedBundleFile(chains, digests, results, md5Result, shaResult); 112 return hook; 113 } 114 115 public void save(DataOutputStream os) throws IOException { 116 getFirstLastID(); 117 if (firstIDSaved == bundledata.getBundleID()) 118 saveChainCache.clear(); 119 if (lastIDSaved == bundledata.getBundleID()) 120 firstIDSaved = lastIDSaved = -1; 121 SignedBundleFile signedFile = signedBundleFile; 122 CertificateChain[] chains = null; 123 String md5Result = null; 124 String shaResult = null; 125 Hashtable digests = null; 126 Hashtable results = null; 127 if (signedFile != null) { 128 chains = signedFile.chains; 129 md5Result = signedFile.manifestMD5Result; 130 shaResult = signedFile.manifestSHAResult; 131 digests = signedFile.digests4entries; 132 results = signedFile.results4entries; 133 } 134 os.writeBoolean(chains != null); 135 if (chains == null) 136 return; 137 os.writeInt(chains.length); 138 for (int i = 0; i < chains.length; i++) { 139 int cacheIdx = saveChainCache.indexOf(chains[i]); 140 os.writeInt(cacheIdx); 141 if (cacheIdx >= 0) 142 continue; 143 saveChainCache.add(chains[i]); 144 os.writeUTF(chains[i].getChain()); 145 os.writeBoolean(chains[i].isTrusted()); 146 Certificate[] certs = chains[i].getCertificates(); 147 os.writeInt(certs == null ? 0 : certs.length); 148 if (certs != null) 149 for (int j = 0; j < certs.length; j++) { 150 byte[] certBytes; 151 try { 152 certBytes = certs[j].getEncoded(); 153 } catch (CertificateEncodingException e) { 154 throw new IOException(e.getMessage()); 155 } 156 os.writeInt(certBytes.length); 157 os.write(certBytes); 158 } 159 os.writeLong(chains[i].getSigningTime() != null ? chains[i].getSigningTime().getTime() : Long.MIN_VALUE); 160 } 161 if (digests == null) 162 os.writeInt(-1); 163 else { 164 os.writeInt(digests.size()); 165 for (Enumeration entries = digests.keys(); entries.hasMoreElements();) { 166 String entry = (String ) entries.nextElement(); 167 String md = (String ) digests.get(entry); 168 byte[] result = (byte[]) results.get(entry); 169 os.writeUTF(entry); 170 if (md == JarVerifierConstant.MD2_STR) 171 os.writeInt(0); 172 else 173 os.writeInt(1); 174 os.writeInt(result.length); 175 os.write(result); 176 } 177 } 178 os.writeBoolean(md5Result != null); 179 if (md5Result != null) 180 os.writeUTF(md5Result); 181 os.writeBoolean(shaResult != null); 182 if (shaResult != null) 183 os.writeUTF(shaResult); 184 } 185 186 private void getFirstLastID() { 187 if (firstIDSaved >= 0) 188 return; 189 Bundle[] bundles = bundledata.getAdaptor().getContext().getBundles(); 190 if (bundles.length > 1) { 191 firstIDSaved = bundles[1].getBundleId(); 192 lastIDSaved = bundles[bundles.length - 1].getBundleId(); 193 } 194 } 195 196 public void copy(StorageHook storageHook) { 197 } 199 200 public void validate() throws IllegalArgumentException { 201 } 203 204 public Dictionary getManifest(boolean firstLoad) throws BundleException { 205 return null; 207 } 208 209 public boolean forgetStatusChange(int status) { 210 return false; 212 } 213 214 public boolean forgetStartLevelChange(int startlevel) { 215 return false; 217 } 218 219 public boolean matchDNChain(String pattern) { 220 return signedBundleFile == null ? false : signedBundleFile.matchDNChain(pattern); 221 } 222 223 public int getKeyHashCode() { 224 return HASHCODE; 225 } 226 227 public boolean compare(KeyedElement other) { 228 return other.getKey() == KEY; 229 } 230 231 public Object getKey() { 232 return KEY; 233 } 234 235 } 236 | Popular Tags |