/* Leech - crawling capabilities for Apache Tika Copyright (C) 2012 DFKI GmbH, Author: Christian Reuschling This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Contact us by mail: christian.reuschling@dfki.de */ /* * Copyright (c) 2005 - 2008 Aduna. * All rights reserved. * * Licensed under the Aperture BSD-style license. */ package de.dfki.km.leech.util.certificates; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.AccessController; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A CertificateStore that can save its certificates to and load them from a file. * * <p> * PersistentCertificateStore internally used a KeyStore to contain its Certificates and optionally * applies a password during load and save. See the KeyStore API documentation for information on how * this password is applied. * * @see java.security.KeyStore */ public class PersistentCertificateStore implements CertificateStore { private Logger logger = LoggerFactory.getLogger(getClass()); private File certificatesFile; private KeyStore keyStore; private char[] password; public PersistentCertificateStore(File certificatesFile, char[] password) { this.certificatesFile = certificatesFile; this.password = password; } public void setPassword(char[] password) { this.password = password; } public char[] getPassword() { return password; } public void load() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { // initialize the KeyStore instance if (keyStore == null) { keyStore = KeyStore.getInstance("JKS"); keyStore.load(null, null); } // load the certificates, if they exist if (certificatesFile.exists()) { FileInputStream stream = new FileInputStream(certificatesFile); BufferedInputStream buffer = new BufferedInputStream(stream); keyStore.load(buffer, password); buffer.close(); stream.close(); } return null; } }); } catch (PrivilegedActionException e) { Exception ex = e.getException(); if (ex instanceof IOException) { throw (IOException) ex; } else if (ex instanceof CertificateException) { throw (CertificateException) ex; } else if (ex instanceof KeyStoreException) { throw (KeyStoreException) ex; } else if (ex instanceof NoSuchAlgorithmException) { throw (NoSuchAlgorithmException) ex; } else { logger.error("Unrecognized nested exception, ignoring", e); } } } public void save() throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { FileOutputStream stream = new FileOutputStream(certificatesFile); BufferedOutputStream buffer = new BufferedOutputStream(stream); keyStore.store(buffer, password); buffer.close(); stream.close(); return null; } }); } catch (PrivilegedActionException e) { Exception ex = e.getException(); if (ex instanceof IOException) { throw (IOException) ex; } else if (ex instanceof CertificateException) { throw (CertificateException) ex; } else if (ex instanceof KeyStoreException) { throw (KeyStoreException) ex; } else if (ex instanceof NoSuchAlgorithmException) { throw (NoSuchAlgorithmException) ex; } else { logger.error("Unrecognized nested exception, ignoring", e); } } } public void add(Certificate certificate) throws KeyStoreException { if (!contains(certificate)) { Random rand = new Random(); String alias = null; // loop until we have a unique alias that is not yet present in the store do { alias = "pcscert" + rand.nextLong(); } while (keyStore.getCertificate(alias) != null); keyStore.setCertificateEntry(alias, certificate); } } public void remove(Certificate certificate) throws KeyStoreException { String alias = keyStore.getCertificateAlias(certificate); if (alias != null) { keyStore.deleteEntry(alias); } } public boolean contains(Certificate certificate) throws KeyStoreException { // a certificate alias is only returned when there is a match String alias = keyStore.getCertificateAlias(certificate); return alias != null; } public boolean verify(Certificate certificate) throws KeyStoreException { // no-op return false; } public Iterator iterator() throws KeyStoreException { HashSet set = new HashSet(); Enumeration aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = (String) aliases.nextElement(); set.add(keyStore.getCertificate(alias)); } return set.iterator(); } }