package org.cagrid.gaards.dorian.federation;
import gov.nih.nci.cagrid.common.FaultHelper;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cagrid.gaards.dorian.stubs.types.DorianInternalFault;
import org.cagrid.gaards.pki.CertUtil;
import org.cagrid.tools.database.Database;
public class CertificateBlacklistManager {
public static final String CERTIFICATE_RENEWED = "CERTIFICATE RENEWED";
public static final String ACCOUNT_DELETED = "ACCOUNT DELETED";
public static final String COMPROMISED = "COMPROMISED";
public static final String TABLE = "certificate_blacklist";
public static final String SERIAL = "SERIAL_NUMBER";
public static final String SUBJECT = "SUBJECT";
public static final String REASON = "REASON";
public static final String CERTIFICATE = "CERTIFICATE";
private boolean dbBuilt = false;
private Database db;
private Log log;
public CertificateBlacklistManager(Database db) {
this.db = db;
log = LogFactory.getLog(this.getClass().getName());
}
public synchronized void addCertificateToBlackList(org.cagrid.gaards.dorian.X509Certificate cert, String reason)
throws DorianInternalFault {
try {
addCertificateToBlackList(CertUtil.loadCertificate(cert.getCertificateAsString()), reason);
} catch (GeneralSecurityException e) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} catch (IOException e) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
}
}
public synchronized void addCertificateToBlackList(X509Certificate cert, String reason) throws DorianInternalFault {
buildDatabase();
if (!memberOfBlackList(cert.getSerialNumber().longValue())) {
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("INSERT INTO " + TABLE + " SET " + SERIAL + "= ?," + SUBJECT
+ "= ?," + REASON + "= ?," + CERTIFICATE + "= ?");
s.setLong(1, cert.getSerialNumber().longValue());
s.setString(2, cert.getSubjectDN().getName());
s.setString(3, reason);
s.setString(4, CertUtil.writeCertificate(cert));
s.executeUpdate();
s.close();
} catch (Exception e) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
}
}
public void removeCertificateFromBlackList(long serialNumber) throws DorianInternalFault {
buildDatabase();
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("delete from " + TABLE + " where " + SERIAL + "= ?");
s.setLong(1, serialNumber);
s.executeUpdate();
s.close();
} catch (Exception e) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
}
public List<Long> getBlackList() throws DorianInternalFault {
buildDatabase();
List<Long> list = new ArrayList<Long>();
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("select " + SERIAL + " from " + TABLE);
ResultSet rs = s.executeQuery();
while (rs.next()) {
list.add(Long.valueOf(rs.getLong(SERIAL)));
}
rs.close();
s.close();
} catch (Exception e) {
log.error(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected error encountered.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
return list;
}
public boolean memberOfBlackList(long id) throws DorianInternalFault {
buildDatabase();
Connection c = null;
boolean exists = false;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("select count(*) from " + TABLE + " WHERE " + SERIAL + "= ?");
s.setLong(1, id);
ResultSet rs = s.executeQuery();
if (rs.next()) {
if (rs.getInt(1) > 0) {
exists = true;
}
}
rs.close();
s.close();
} catch (Exception e) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Database Error");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
return exists;
}
public void buildDatabase() throws DorianInternalFault {
if (!dbBuilt) {
try {
if (!this.db.tableExists(TABLE)) {
String certificates = "CREATE TABLE " + TABLE + " (" + SERIAL + " BIGINT PRIMARY KEY," + SUBJECT
+ " TEXT NOT NULL," + REASON + " VARCHAR(255) NOT NULL," + CERTIFICATE + " TEXT,"
+ "INDEX document_index (" + SERIAL + "));";
db.update(certificates);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("An unexpected database error occurred.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
}
this.dbBuilt = true;
}
}
public void clearDatabase() throws DorianInternalFault {
buildDatabase();
try {
db.update("delete from " + TABLE);
} catch (Exception e) {
log.error(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("An unexpected database error occurred.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
}
}
}