package org.cagrid.gaards.dorian.ca;
import gov.nih.nci.cagrid.common.FaultHelper;
import java.io.ByteArrayInputStream;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.cagrid.gaards.dorian.common.LoggingObject;
import org.cagrid.gaards.dorian.stubs.types.DorianInternalFault;
import org.cagrid.gaards.pki.CertUtil;
import org.cagrid.gaards.pki.KeyUtil;
import org.cagrid.tools.database.Database;
/**
* @author <A href="mailto:langella@bmi.osu.edu">Stephen Langella </A>
* @author <A href="mailto:oster@bmi.osu.edu">Scott Oster </A>
* @author <A href="mailto:hastings@bmi.osu.edu">Shannon Hastings </A>
* @version $Id: ArgumentManagerTable.java,v 1.2 2004/10/15 16:35:16 langella
* Exp $
*/
public class CredentialsManager extends LoggingObject {
public static String CREDENTIALS_TABLE = "certificate_authority";
private Database db;
private boolean dbBuilt = false;
public CredentialsManager(Database db) {
this.db = db;
}
public boolean hasCredentials(String alias) throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
boolean exists = false;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("select count(*) from " + CREDENTIALS_TABLE + " where ALIAS= ?");
s.setString(1, alias);
ResultSet rs = s.executeQuery();
if (rs.next()) {
int count = rs.getInt(1);
if (count > 0) {
exists = true;
}
}
rs.close();
s.close();
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Database Error, Error determining if the user " + alias
+ " has credentials.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
return exists;
}
public void deleteCredentials(String alias) throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("delete from " + CREDENTIALS_TABLE + " where ALIAS= ? ");
s.setString(1, alias);
s.execute();
s.close();
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Database Error, Error removing the credentials for the user " + alias
+ "!!!");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
}
public void addCredentials(String alias, String password, X509Certificate cert, PrivateKey key)
throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
try {
if (!hasCredentials(alias)) {
c = db.getConnection();
long serial = cert.getSerialNumber().longValue();
String keyStr = KeyUtil.writePrivateKey(key, password);
String certStr = CertUtil.writeCertificate(cert);
PreparedStatement s = c.prepareStatement("INSERT INTO " + CREDENTIALS_TABLE
+ " SET ALIAS= ?, SERIAL_NUMBER= ?, CERTIFICATE= ?, PRIVATE_KEY= ?");
s.setString(1, alias);
s.setLong(2, serial);
s.setString(3, certStr);
s.setString(4, keyStr);
s.execute();
s.close();
}
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error, could not add credentials to the credentials database.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
}
public void addCertificate(String alias, X509Certificate cert) throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
try {
if (!hasCredentials(alias)) {
c = db.getConnection();
long serial = cert.getSerialNumber().longValue();
String keyStr = "";
String certStr = CertUtil.writeCertificate(cert);
PreparedStatement s = c.prepareStatement("INSERT INTO " + CREDENTIALS_TABLE
+ " SET ALIAS= ?, SERIAL_NUMBER= ?, CERTIFICATE= ?, PRIVATE_KEY= ?");
s.setString(1, alias);
s.setLong(2, serial);
s.setString(3, certStr);
s.setString(4, keyStr);
s.execute();
s.close();
}
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Error, could not add certificate to the credentials database.");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
}
public PrivateKey getPrivateKey(String alias, String password) throws DorianInternalFault, InvalidPasswordFault {
this.buildDatabase();
Connection c = null;
PrivateKey key = null;
String keyStr = null;
try {
c = db.getConnection();
PreparedStatement s = c
.prepareStatement("select PRIVATE_KEY from " + CREDENTIALS_TABLE + " where ALIAS= ?");
s.setString(1, alias);
ResultSet rs = s.executeQuery();
if (rs.next()) {
keyStr = rs.getString("PRIVATE_KEY");
}
rs.close();
s.close();
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Database Error, Error obtaining the private key for the user " + alias
+ ".");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
if (keyStr == null || keyStr.trim().equals("")) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("No PrivateKey exists for the user " + alias + ".");
throw fault;
}
try {
key = KeyUtil.loadPrivateKey(new ByteArrayInputStream(keyStr.getBytes()), password);
} catch (Exception e) {
InvalidPasswordFault fault = new InvalidPasswordFault();
fault.setFaultString("Invalid Password Specified.");
throw fault;
}
return key;
}
public X509Certificate getCertificate(String alias) throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
X509Certificate cert = null;
try {
c = db.getConnection();
PreparedStatement s = c
.prepareStatement("select CERTIFICATE from " + CREDENTIALS_TABLE + " where ALIAS= ?");
s.setString(1, alias);
ResultSet rs = s.executeQuery();
if (rs.next()) {
String certStr = rs.getString("CERTIFICATE");
cert = CertUtil.loadCertificate(certStr);
}
rs.close();
s.close();
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("Unexpected Database Error, Error obtaining the certificate for the user " + alias
+ ".");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
if (cert == null) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("No Certificate exists for the user " + alias + ".");
throw fault;
}
return cert;
}
public long getCertificateSerialNumber(String alias) throws DorianInternalFault {
this.buildDatabase();
Connection c = null;
long sn = -1;
try {
c = db.getConnection();
PreparedStatement s = c.prepareStatement("select SERIAL_NUMBER from " + CREDENTIALS_TABLE
+ " where ALIAS= ?");
s.setString(1, alias);
ResultSet rs = s.executeQuery();
if (rs.next()) {
sn = rs.getLong("SERIAL_NUMBER");
}
rs.close();
s.close();
} catch (Exception e) {
logError(e.getMessage(), e);
DorianInternalFault fault = new DorianInternalFault();
fault
.setFaultString("Unexpected Database Error, Error obtaining the certificate serial number for the user "
+ alias + ".");
FaultHelper helper = new FaultHelper(fault);
helper.addFaultCause(e);
fault = (DorianInternalFault) helper.getFault();
throw fault;
} finally {
db.releaseConnection(c);
}
if (sn == -1) {
DorianInternalFault fault = new DorianInternalFault();
fault.setFaultString("No Certificate exists for the user " + alias + ".");
throw fault;
}
return sn;
}
private synchronized void buildDatabase() throws DorianInternalFault {
try {
if (!dbBuilt) {
if (!this.db.tableExists(CREDENTIALS_TABLE)) {
String users = "CREATE TABLE " + CREDENTIALS_TABLE + " ("
+ "ALIAS VARCHAR(255) NOT NULL PRIMARY KEY," + " SERIAL_NUMBER BIGINT NOT NULL,"
+ "CERTIFICATE TEXT NOT NULL," + "PRIVATE_KEY TEXT NOT NULL,"
+ "INDEX document_index (ALIAS));";
db.update(users);
}
this.dbBuilt = true;
}
} catch (Exception e) {
logError(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;
}
}
public void clearDatabase() throws DorianInternalFault {
buildDatabase();
try {
db.update("delete from " + CREDENTIALS_TABLE);
} catch (Exception e) {
logError(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;
}
}
}