/* This code is part of Freenet. It is distributed under the GNU General * Public License, version 2 (or at your option any later version). See * http://www.gnu.org/ for further details of the GPL. */ package freenet.pluginmanager; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.Collection; import java.util.Iterator; import freenet.pluginmanager.PluginManager.PluginProgress; import freenet.support.api.Bucket; import freenet.support.io.ArrayBucket; import freenet.support.io.Closer; import freenet.support.io.FileBucket; import freenet.support.io.FileUtil; public class PluginDownLoaderOfficialHTTPS extends PluginDownLoaderURL { private static final String certurlNew = "freenet/clients/http/staticfiles/globalsign.pem"; // amazon root certificate, so we can rekey the S3-based site more easily private static final String certurlAmazon1 = "freenet/clients/http/staticfiles/AmazonRootCA1.pem"; private static final String certurlAmazon2 = "freenet/clients/http/staticfiles/AmazonRootCA2.pem"; private static final String certurlAmazon3 = "freenet/clients/http/staticfiles/AmazonRootCA3.pem"; private static final String certurlAmazon4 = "freenet/clients/http/staticfiles/AmazonRootCA4.pem"; private static final String[] certURLs = new String[] { certurlNew, certurlAmazon1, certurlAmazon2, certurlAmazon3, certurlAmazon4}; public static final String certfileOld = "startssl.pem"; private static final String certfile = "sslcerts.pem"; @Override public URL checkSource(String source) throws PluginNotFoundException { return super.checkSource("https://downloads.freenetproject.org/latest/" + source + ".jar"); } @Override String getPluginName(String source) throws PluginNotFoundException { return source + ".jar"; } @Override String getSHA1sum() throws PluginNotFoundException { try { URL sha1url = new URL(getSource().toString()+".sha1"); URLConnection urlConnection = sha1url.openConnection(); urlConnection.setUseCaches(false); urlConnection.setAllowUserInteraction(false); InputStream is = openConnectionCheckRedirects(urlConnection); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int read; while ((read = is.read(buffer)) != -1) { bos.write(buffer, 0, read); } return new String(bos.toByteArray(), "ISO-8859-1").split(" ")[0]; } catch (MalformedURLException e) { throw new PluginNotFoundException("impossible: "+e,e); } catch (IOException e) { throw new PluginNotFoundException("Error while fetching sha1 for plugin: "+e,e); } } @Override InputStream getInputStream(PluginProgress progress) throws IOException { File TMP_KEYSTORE = null; FileInputStream fis = null; InputStream is = null; try { TMP_KEYSTORE = File.createTempFile("keystore", ".tmp"); TMP_KEYSTORE.deleteOnExit(); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, new char[0]); is = getCert(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); Collection<? extends Certificate> c = cf.generateCertificates(is); Iterator<? extends Certificate> it = c.iterator(); while(it.hasNext()) { Certificate cert = it.next(); ks.setCertificateEntry(cert.getPublicKey().toString(), cert); } FileOutputStream tmpFOS = new FileOutputStream(TMP_KEYSTORE); try { ks.store(tmpFOS, new char[0]); } finally { Closer.close(tmpFOS); } System.out.println("The CA has been imported into the trustStore"); } catch(Exception e) { System.err.println("Error while handling the CA :" + e.getMessage()); throw new IOException("Error while handling the CA : "+e); } finally { Closer.close(fis); } System.setProperty("javax.net.ssl.trustStore", TMP_KEYSTORE.toString()); return super.getInputStream(progress); } private InputStream getCert() throws IOException { // normal the file should be here, // left by installer or update script File certFile = new File(certfile).getAbsoluteFile(); if (certFile.exists()) { return new FileInputStream(certFile); } Bucket bucket; OutputStream os = null; try { try { bucket = new FileBucket(certFile, false, false, false, false); os = bucket.getOutputStream(); writeCerts(os); // If this fails, we need the whole fetch to fail. os.close(); os = null; } finally { Closer.close(os); } return bucket.getInputStream(); } catch (IOException e) { // We don't have access to TempBucketFactory here. // But the certs should be small, so just keep them in memory. bucket = new ArrayBucket(); os = bucket.getOutputStream(); writeCerts(os); os.close(); return bucket.getInputStream(); } } private static void writeCerts(OutputStream os) throws IOException { // try to create pem file ClassLoader loader = ClassLoader.getSystemClassLoader(); InputStream in = null; for(String certurl : certURLs) { try { in = loader.getResourceAsStream(certurl); if (in != null) { FileUtil.copy(in, os, -1); } else { throw new IOException("Could not find certificates in fred source nor find certificates file"); } } finally { if (in != null) { in.close(); } } } } /** For the benefit mainly of the Windows updater script. * It uses startssl.pem */ public static void writeCertsTo(File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); writeCerts(fos); fos.close(); } public boolean isOfficialPluginLoader() { return true; } }