Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* DSS - Digital Signature Services
* Copyright (C) 2015 European Commission, provided under the CEF programme
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package eu.europa.esig.dss.client.crl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europa.esig.dss.DSSASN1Utils;
import eu.europa.esig.dss.DSSException;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.SignatureAlgorithm;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.x509.CertificateToken;
import eu.europa.esig.dss.x509.crl.CRLSource;
import eu.europa.esig.dss.x509.crl.CRLToken;
import eu.europa.esig.dss.x509.crl.CRLValidity;
/**
* CRLSource that retrieve information from a JDBC datasource
*/
public class JdbcCacheCRLSource implements CRLSource {
private static final Logger LOG = LoggerFactory.getLogger(JdbcCacheCRLSource.class);
/**
* used in the init method to check if the table exists
*/
private static final String SQL_INIT_CHECK_EXISTENCE = "SELECT COUNT(*) FROM CACHED_CRL";
/**
* used in the init method to create the table, if not existing: ID (char40 = SHA1 length) and DATA (blob)
*/
private static final String SQL_INIT_CREATE_TABLE = "CREATE TABLE CACHED_CRL (ID CHAR(40), DATA LONGVARBINARY, SIGNATURE_ALGORITHM VARCHAR(20), THIS_UPDATE TIMESTAMP, NEXT_UPDATE TIMESTAMP, EXPIRED_CERTS_ON_CRL TIMESTAMP, ISSUER LONGVARBINARY, ISSUER_PRINCIPAL_MATCH BOOLEAN, SIGNATURE_INTACT BOOLEAN, CRL_SIGN_KEY_USAGE BOOLEAN, UNKNOWN_CRITICAL_EXTENSION BOOLEAN, SIGNATURE_INVALID_REASON VARCHAR(256))";
/**
* used in the find method to select the crl via the id
*/
private static final String SQL_FIND_QUERY = "SELECT * FROM CACHED_CRL WHERE ID = ?";
/**
* used in the find method when selecting the crl via the id to get the ID (char20) from the resultset
*/
private static final String SQL_FIND_QUERY_ID = "ID";
/**
* used in the find method when selecting the crl via the id to get the DATA (blob) from the resultset
*/
private static final String SQL_FIND_QUERY_DATA = "DATA";
/**
* used in the find method when selecting the issuer certificate via the id to get the ISSUER (blob) from the
* resultset
*/
private static final String SQL_FIND_QUERY_ISSUER = "ISSUER";
private static final String SQL_FIND_QUERY_THIS_UPDATE = "THIS_UPDATE";
private static final String SQL_FIND_QUERY_NEXT_UPDATE = "NEXT_UPDATE";
private static final String SQL_FIND_QUERY_EXPIRED_CERTS_ON_CRL = "EXPIRED_CERTS_ON_CRL";
private static final String SQL_FIND_QUERY_SIGNATURE_ALGO = "SIGNATURE_ALGORITHM";
private static final String SQL_FIND_QUERY_ISSUER_PRINCIPAL_MATCH = "ISSUER_PRINCIPAL_MATCH";
private static final String SQL_FIND_QUERY_SIGNATURE_INTACT = "SIGNATURE_INTACT";
private static final String SQL_FIND_QUERY_CRL_SIGN_KEY_USAGE = "CRL_SIGN_KEY_USAGE";
private static final String SQL_FIND_QUERY_UNKNOWN_CRITICAL_EXTENSION = "UNKNOWN_CRITICAL_EXTENSION";
private static final String SQL_FIND_QUERY_SIGNATURE_INVALID_REASON = "SIGNATURE_INVALID_REASON";
/**
* used via the find method to insert a new record
*/
private static final String SQL_FIND_INSERT = "INSERT INTO CACHED_CRL (ID, DATA, SIGNATURE_ALGORITHM, THIS_UPDATE, NEXT_UPDATE, EXPIRED_CERTS_ON_CRL, ISSUER, ISSUER_PRINCIPAL_MATCH, SIGNATURE_INTACT, CRL_SIGN_KEY_USAGE, UNKNOWN_CRITICAL_EXTENSION, SIGNATURE_INVALID_REASON) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
/**
* used via the find method to update an existing record via the id
*/
private static final String SQL_FIND_UPDATE = "UPDATE CACHED_CRL SET DATA = ?, SIGNATURE_ALGORITHM = ?, THIS_UPDATE = ?, NEXT_UPDATE = ?, EXPIRED_CERTS_ON_CRL = ?, ISSUER = ?, ISSUER_PRINCIPAL_MATCH = ?, SIGNATURE_INTACT = ?, CRL_SIGN_KEY_USAGE = ?, UNKNOWN_CRITICAL_EXTENSION = ?, SIGNATURE_INVALID_REASON = ? WHERE ID = ?";
private OnlineCRLSource cachedSource;
private DataSource dataSource;
/**
* The default constructor for JdbcCRLSource.
*/
public JdbcCacheCRLSource() {
}
@Override
public CRLToken findCrl(final CertificateToken certificateToken) throws DSSException {
if (certificateToken == null) {
return null;
}
final CertificateToken issuerToken = certificateToken.getIssuerToken();
if (issuerToken == null) {
return null;
}
final List crlUrls = DSSASN1Utils.getCrlUrls(certificateToken);
if (Utils.isCollectionEmpty(crlUrls)) {
return null;
}
final String crlUrl = crlUrls.get(0);
LOG.info("CRL's URL for " + certificateToken.getAbbreviation() + " : " + crlUrl);
try {
final String key = DSSUtils.getSHA1Digest(crlUrl);
final CRLValidity storedValidity = findCrlInDB(key);
if (storedValidity != null) {
if (storedValidity.getNextUpdate().after(new Date())) {
LOG.debug("CRL in cache");
final CRLToken crlToken = new CRLToken(certificateToken, storedValidity);
crlToken.setSourceURL(crlUrl);
if (crlToken.isValid()) {
return crlToken;
}
}
}
final CRLToken crlToken = cachedSource.findCrl(certificateToken);
if ((crlToken != null) && crlToken.isValid()) {
if (storedValidity == null) {
LOG.info("CRL '{}' not in cache", crlUrl);
insertCrlInDb(key, crlToken.getCrlValidity());
} else {
LOG.debug("CRL '{}' expired", crlUrl);
updateCrlInDb(key, crlToken.getCrlValidity());
}
}
return crlToken;
} catch (SQLException e) {
LOG.info("Error with the cache data store", e);
}
return null;
}
/**
* @param cachedSource
* the cachedSource to set
*/
public void setCachedSource(OnlineCRLSource cachedSource) {
this.cachedSource = cachedSource;
}
/**
* Initialise the DAO by creating the table if it does not exist.
*
* @throws Exception
*/
private void initDao() throws Exception {
/* Create the table if it doesn't exist. */
if (!tableExists()) {
createTable();
}
}
/**
* Create the cache crl table if it does not exist
*
* @throws java.sql.SQLException
*/
private void createTable() throws SQLException {
Connection c = null;
Statement s = null;
try {
c = getDataSource().getConnection();
s = c.createStatement();
s.executeQuery(SQL_INIT_CREATE_TABLE);
c.commit();
} finally {
closeQuietly(c, s, null);
}
}
/**
* Check if the cache table exists
*
* @return true if the table exists.
*/
private boolean tableExists() {
Connection c = null;
Statement s = null;
boolean tableExists;
try {
c = getDataSource().getConnection();
s = c.createStatement();
s.executeQuery(SQL_INIT_CHECK_EXISTENCE);
tableExists = true;
} catch (SQLException e) {
tableExists = false;
} finally {
closeQuietly(c, s, null);
}
return tableExists;
}
/**
* Get the cached CRL from the datasource
*
* @param key
* the key of the CRL
* @return the cached crl
* @throws java.sql.SQLException
*/
private CRLValidity findCrlInDB(String key) throws SQLException {
Connection c = null;
PreparedStatement s = null;
ResultSet rs = null;
try {
c = getDataSource().getConnection();
s = c.prepareStatement(SQL_FIND_QUERY);
s.setString(1, key);
rs = s.executeQuery();
if (rs.next()) {
CRLValidity cached = new CRLValidity();
cached.setKey(rs.getString(SQL_FIND_QUERY_ID));
cached.setCrlEncoded(rs.getBytes(SQL_FIND_QUERY_DATA));
cached.setSignatureAlgorithm(SignatureAlgorithm.valueOf(rs.getString(SQL_FIND_QUERY_SIGNATURE_ALGO)));
cached.setThisUpdate(rs.getTimestamp(SQL_FIND_QUERY_THIS_UPDATE));
cached.setNextUpdate(rs.getTimestamp(SQL_FIND_QUERY_NEXT_UPDATE));
cached.setExpiredCertsOnCRL(rs.getTimestamp(SQL_FIND_QUERY_EXPIRED_CERTS_ON_CRL));
cached.setIssuerToken(DSSUtils.loadCertificate(rs.getBytes(SQL_FIND_QUERY_ISSUER)));
cached.setCrlSignKeyUsage(rs.getBoolean(SQL_FIND_QUERY_CRL_SIGN_KEY_USAGE));
cached.setUnknownCriticalExtension(rs.getBoolean(SQL_FIND_QUERY_UNKNOWN_CRITICAL_EXTENSION));
cached.setIssuerX509PrincipalMatches(rs.getBoolean(SQL_FIND_QUERY_ISSUER_PRINCIPAL_MATCH));
cached.setSignatureIntact(rs.getBoolean(SQL_FIND_QUERY_SIGNATURE_INTACT));
cached.setSignatureInvalidityReason(rs.getString(SQL_FIND_QUERY_SIGNATURE_INVALID_REASON));
return cached;
}
} finally {
closeQuietly(c, s, rs);
}
return null;
}
/**
* Insert a new CRL into the cache
*
* @param key
* the key
* @param encoded
* the encoded CRL
* @throws java.sql.SQLException
*/
private void insertCrlInDb(String key, CRLValidity token) throws SQLException {
Connection c = null;
PreparedStatement s = null;
ResultSet rs = null;
try {
c = getDataSource().getConnection();
s = c.prepareStatement(SQL_FIND_INSERT);
s.setString(1, key);
s.setBytes(2, token.getCrlEncoded());
s.setString(3, token.getSignatureAlgorithm().name());
if (token.getThisUpdate() != null) {
s.setTimestamp(4, new Timestamp(token.getThisUpdate().getTime()));
} else {
s.setNull(4, Types.TIMESTAMP);
}
if (token.getNextUpdate() != null) {
s.setTimestamp(5, new Timestamp(token.getNextUpdate().getTime()));
} else {
s.setNull(5, Types.TIMESTAMP);
}
if (token.getExpiredCertsOnCRL() != null) {
s.setTimestamp(6, new Timestamp(token.getExpiredCertsOnCRL().getTime()));
} else {
s.setNull(6, Types.TIMESTAMP);
}
s.setBytes(7, token.getIssuerToken().getEncoded());
s.setBoolean(8, token.isIssuerX509PrincipalMatches());
s.setBoolean(9, token.isSignatureIntact());
s.setBoolean(10, token.isCrlSignKeyUsage());
s.setBoolean(11, token.isUnknownCriticalExtension());
s.setString(12, token.getSignatureInvalidityReason());
s.executeUpdate();
} finally {
closeQuietly(c, s, rs);
}
}
/**
* Update the cache with the CRL
*
* @param key
* the key
* @param encoded
* the encoded CRL
* @throws java.sql.SQLException
*/
private void updateCrlInDb(String key, CRLValidity token) throws SQLException {
Connection c = null;
PreparedStatement s = null;
ResultSet rs = null;
try {
c = getDataSource().getConnection();
s = c.prepareStatement(SQL_FIND_UPDATE);
s.setBytes(1, token.getCrlEncoded());
s.setString(2, token.getSignatureAlgorithm().name());
if (token.getThisUpdate() != null) {
s.setTimestamp(3, new Timestamp(token.getThisUpdate().getTime()));
} else {
s.setNull(3, Types.TIMESTAMP);
}
if (token.getNextUpdate() != null) {
s.setTimestamp(4, new Timestamp(token.getNextUpdate().getTime()));
} else {
s.setNull(4, Types.TIMESTAMP);
}
if (token.getExpiredCertsOnCRL() != null) {
s.setTimestamp(5, new Timestamp(token.getExpiredCertsOnCRL().getTime()));
} else {
s.setNull(5, Types.TIMESTAMP);
}
s.setBytes(6, token.getIssuerToken().getEncoded());
s.setBoolean(7, token.isIssuerX509PrincipalMatches());
s.setBoolean(8, token.isSignatureIntact());
s.setBoolean(9, token.isCrlSignKeyUsage());
s.setBoolean(10, token.isUnknownCriticalExtension());
s.setString(11, token.getSignatureInvalidityReason());
s.setString(12, key);
s.executeUpdate();
} finally {
closeQuietly(c, s, rs);
}
}
/**
* @return the dataSource
*/
private DataSource getDataSource() {
return dataSource;
}
/**
* @param dataSource
* the dataSource to set
* @throws Exception
*/
public void setDataSource(DataSource dataSource) throws Exception {
this.dataSource = dataSource;
initDao();
}
/**
* Close the statement and connection and resultset without throwing the exception
*
* @param c
* the connection
* @param s
* the statement
* @param rs
* the ResultSet
*/
private void closeQuietly(Connection c, Statement s, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
if (s != null) {
s.close();
}
if (c != null) {
c.close();
}
} catch (SQLException e) {
// purposely empty
}
}
}