package org.cagrid.cds.service.impl.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.cagrid.cds.model.CertificateChain;
import org.cagrid.cds.model.ClientDelegationFilter;
import org.cagrid.cds.model.DelegatedCredentialAuditFilter;
import org.cagrid.cds.model.DelegatedCredentialAuditRecord;
import org.cagrid.cds.model.DelegatedCredentialEvent;
import org.cagrid.cds.model.DelegationIdentifier;
import org.cagrid.cds.model.DelegationPolicy;
import org.cagrid.cds.model.DelegationRecord;
import org.cagrid.cds.model.DelegationRecordFilter;
import org.cagrid.cds.model.DelegationRequest;
import org.cagrid.cds.model.DelegationSigningRequest;
import org.cagrid.cds.model.DelegationSigningResponse;
import org.cagrid.cds.model.DelegationStatus;
import org.cagrid.cds.model.ExpirationStatus;
import org.cagrid.cds.model.ProxyLifetime;
import org.cagrid.cds.model.PublicKey;
import org.cagrid.cds.service.impl.util.Errors;
import org.cagrid.cds.service.impl.util.ProxyPolicy;
import org.cagrid.cds.service.impl.util.Utils;
import org.cagrid.cds.service.impl.policy.PolicyHandler;
import org.cagrid.cds.service.exception.CDSInternalException;
import org.cagrid.cds.service.exception.DelegationException;
import org.cagrid.cds.service.exception.InvalidPolicyException;
import org.cagrid.cds.service.exception.PermissionDeniedException;
import org.cagrid.gaards.pki.CertificateExtensionsUtil;
import org.cagrid.gaards.pki.KeyUtil;
import org.cagrid.gaards.pki.ProxyCreator;
import org.cagrid.tools.database.Database;
import org.cagrid.tools.events.Event;
import org.cagrid.tools.events.EventAuditor;
import org.cagrid.tools.events.EventManager;
import org.cagrid.tools.events.InvalidHandlerException;
import org.globus.gsi.CertUtil;
import org.globus.gsi.CertificateRevocationLists;
import org.globus.gsi.TrustedCertificates;
import org.globus.gsi.bc.BouncyCastleUtil;
import org.globus.gsi.proxy.ProxyPathValidator;
import java.security.KeyPair;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
public class DelegatedCredentialManager {
public static int DELEGATION_BUFFER_SECONDS = 120;
private final static String TABLE = "delegated_credentials";
private final static String DELEGATION_ID = "DELEGATION_ID";
private final static String GRID_IDENTITY = "GRID_IDENTITY";
private final static String STATUS = "STATUS";
private final static String POLICY_TYPE = "POLICY_TYPE";
private final static String EXPIRATION = "EXPIRATION";
private final static String DELEGATION_PATH_LENGTH = "DELEGATION_PATH_LENGTH";
private final static String DATE_INITIATED = "DATE_INITIATED";
private final static String DATE_APPROVED = "DATE_APPROVED";
private final static String PROXY_LIFETIME_HOURS = "PROXY_LIFETIME_HOURS";
private final static String PROXY_LIFETIME_MINUTES = "PROXY_LIFETIME_MINUTES";
private final static String PROXY_LIFETIME_SECONDS = "PROXY_LIFETIME_SECONDS";
private final static String DELEGATED_CREDENTIAL_AUDITOR = "delegatedCredentialAuditor";
public static int PROXY_EXPIRATION_BUFFER_SECONDS = 5;
private Database db;
private boolean dbBuilt = false;
private List<PolicyHandler> handlers;
private Log log;
private KeyManager keyManager;
private ProxyPolicy proxyPolicy;
private EventManager events;
private EventAuditor delegationAuditor;
public DelegatedCredentialManager(Database db, PropertyManager properties, KeyManager keyManager, List<PolicyHandler> policyHandlers,
ProxyPolicy proxyPolicy, EventManager events) throws CDSInternalException {
this.db = db;
this.log = LogFactory.getLog(this.getClass().getName());
this.handlers = policyHandlers;
this.proxyPolicy = proxyPolicy;
this.events = events;
try {
this.delegationAuditor = (EventAuditor) events.getEventHandler(DELEGATED_CREDENTIAL_AUDITOR);
} catch (InvalidHandlerException e) {
throw Errors.makeException(CDSInternalException.class,
"Could not initialize the delegation credential manager, could not obtain the delegated credential auditor.", e);
}
String currentKeyManager = properties.getKeyManager();
if ((currentKeyManager != null) && (!currentKeyManager.equals(keyManager.getName()))) {
throw Errors.makeException(CDSInternalException.class, Errors.KEY_MANAGER_CHANGED);
}
this.keyManager = keyManager;
if (currentKeyManager == null) {
properties.setKeyManager(this.keyManager.getName());
}
}
public PolicyHandler findHandler(String policyClassName) throws InvalidPolicyException {
PolicyHandler handler = null;
boolean handlerFound = false;
for (int i = 0; i < handlers.size(); i++) {
if (handlers.get(i).isSupported(policyClassName)) {
if (!handlerFound) {
handler = handlers.get(i);
handlerFound = true;
} else {
throw Errors.makeException(InvalidPolicyException.class, Errors.MULTIPLE_HANDLERS_FOUND_FOR_POLICY + policyClassName
+ ", cannot decide which handler to employ.");
}
}
}
if (!handlerFound) {
throw Errors.makeException(InvalidPolicyException.class, Errors.DELEGATION_POLICY_NOT_SUPPORTED);
}
return handler;
}
public List<DelegatedCredentialAuditRecord> searchAuditLog(DelegatedCredentialAuditFilter f) throws CDSInternalException {
try {
String targetId = null;
if (f.getDelegationIdentifier() != null) {
targetId = String.valueOf(f.getDelegationIdentifier().getDelegationId());
}
String eventType = null;
if (f.getEvent() != null) {
eventType = f.getEvent().value();
}
Date start = null;
if (f.getStartDate() != null) {
start = new Date(f.getStartDate().longValue());
}
Date end = null;
if (f.getEndDate() != null) {
end = new Date(f.getEndDate().longValue());
}
List<Event> events = this.delegationAuditor.findEvents(targetId, f.getSourceGridIdentity(), eventType, start, end, null);
List<DelegatedCredentialAuditRecord> records = new ArrayList<DelegatedCredentialAuditRecord>();
for (int i = 0; i < events.size(); i++) {
DelegatedCredentialAuditRecord record = new DelegatedCredentialAuditRecord();
DelegationIdentifier id = new DelegationIdentifier();
id.setDelegationId(Long.valueOf(events.get(i).getTargetId()).longValue());
record.setDelegationIdentifier(id);
record.setEvent(DelegatedCredentialEvent.fromValue(events.get(i).getEventType()));
record.setMessage(events.get(i).getMessage());
record.setOccurredAt(events.get(i).getOccurredAt());
record.setSourceGridIdentity(events.get(i).getReportingPartyId());
records.add(record);
}
return records;
} catch (Exception e) {
throw Errors.makeException(CDSInternalException.class, "An unexpected error occurred in searching the audit logs.", e);
}
}
public List<DelegationRecord> findCredentialsDelegatedToClient(String callerIdentity, ClientDelegationFilter filter) throws CDSInternalException {
DelegationRecordFilter f = new DelegationRecordFilter();
f.setDelegationStatus(DelegationStatus.APPROVED);
f.setExpirationStatus(ExpirationStatus.VALID);
if (filter != null) {
f.setGridIdentity(filter.getGridIdentity());
}
List<DelegationRecord> records = findDelegatedCredentials(f);
if (records != null) {
List<DelegationRecord> list = new ArrayList<DelegationRecord>();
for (DelegationRecord record : records) {
try {
PolicyHandler handler = this.findHandler(record.getDelegationPolicy().getClass().getName());
if (handler.isAuthorized(record.getDelegationIdentifier(), callerIdentity)) {
list.add(record);
}
} catch (Exception e) {
log.error(e);
}
}
return list;
} else {
return Collections.emptyList();
}
}
public synchronized DelegationSigningRequest initiateDelegation(String callerGridIdentity, DelegationRequest request) throws CDSInternalException,
DelegationException, InvalidPolicyException {
this.buildDatabase();
DelegationPolicy policy = request.getDelegationPolicy();
PolicyHandler handler = this.findHandler(policy.getClass().getName());
if (!this.proxyPolicy.isKeySizeSupported(request.getKeyLength())) {
throw Errors.makeException(DelegationException.class, Errors.INVALID_KEY_LENGTH_SPECIFIED);
}
if (request.getIssuedCredentialLifetime() == null) {
throw Errors.makeException(DelegationException.class, Errors.PROXY_LIFETIME_NOT_SPECIFIED);
}
if ((request.getIssuedCredentialPathLength() < 0) || (this.proxyPolicy.getMaxDelegationPathLength() < request.getIssuedCredentialPathLength())) {
throw Errors.makeException(DelegationException.class, Errors.INVALID_DELEGATION_PATH_LENGTH_SPECIFIED);
}
Connection c = null;
long delegationId = -1;
try {
c = this.db.getConnection();
PreparedStatement s = c.prepareStatement("INSERT INTO " + TABLE + " SET " + GRID_IDENTITY + "= ?, " + POLICY_TYPE + "= ?, " + STATUS + "= ?,"
+ DATE_INITIATED + "=?," + DATE_APPROVED + "=?," + EXPIRATION + "=?," + DELEGATION_PATH_LENGTH + "=?," + PROXY_LIFETIME_HOURS + "=?,"
+ PROXY_LIFETIME_MINUTES + "=?," + PROXY_LIFETIME_SECONDS + "=?");
s.setString(1, callerGridIdentity);
s.setString(2, policy.getClass().getName());
s.setString(3, DelegationStatus.PENDING.value());
s.setLong(4, new Date().getTime());
s.setLong(5, 0);
s.setLong(6, 0);
s.setInt(7, request.getIssuedCredentialPathLength());
s.setInt(8, request.getIssuedCredentialLifetime().getHours());
s.setInt(9, request.getIssuedCredentialLifetime().getMinutes());
s.setInt(10, request.getIssuedCredentialLifetime().getSeconds());
s.execute();
s.close();
delegationId = db.getLastAutoId(c);
DelegationIdentifier id = new DelegationIdentifier();
id.setDelegationId(delegationId);
// Create and Store Key Pair.
KeyPair keys = this.keyManager.createAndStoreKeyPair(String.valueOf(delegationId), request.getKeyLength());
handler.storePolicy(id, policy);
DelegationSigningRequest req = new DelegationSigningRequest();
req.setDelegationIdentifier(id);
PublicKey publicKey = new PublicKey();
publicKey.setKeyAsString(KeyUtil.writePublicKey(keys.getPublic()));
req.setPublicKey(publicKey);
logEvent(delegationId, callerGridIdentity, DelegatedCredentialEvent.DELEGATION_INITIATED, "Delegation initiated for " + callerGridIdentity + ".");
return req;
} catch (CDSInternalException e) {
try {
this.delete(delegationId);
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
}
throw e;
} catch (InvalidPolicyException e) {
try {
this.delete(delegationId);
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
}
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
try {
this.delete(delegationId);
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
}
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
db.releaseConnection(c);
}
}
private void logEvent(long delegationId, String callerGridIdentity, DelegatedCredentialEvent event, String message) throws CDSInternalException {
try {
events.logEvent(String.valueOf(delegationId), callerGridIdentity, event.value(), message);
} catch (Exception e) {
throw Errors.makeException(CDSInternalException.class, "Unexpected error encountered in establishing the audit trail.", e);
}
}
public boolean delegationExists(DelegationIdentifier id) throws CDSInternalException {
try {
if (id == null) {
return false;
} else {
return db.exists(TABLE, DELEGATION_ID, id.getDelegationId());
}
} catch (Exception e) {
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
}
}
public DelegationRecord getDelegationRecord(DelegationIdentifier id) throws CDSInternalException, DelegationException {
if (delegationExists(id)) {
DelegationRecord r = new DelegationRecord();
r.setDelegationIdentifier(id);
Connection c = null;
try {
c = this.db.getConnection();
PreparedStatement s = c.prepareStatement("select * from " + TABLE + " WHERE " + DELEGATION_ID + "= ?");
s.setLong(1, id.getDelegationId());
ResultSet rs = s.executeQuery();
if (rs.next()) {
r.setDateApproved(rs.getLong(DATE_APPROVED));
r.setDateInitiated(rs.getLong(DATE_INITIATED));
r.setDelegationStatus(DelegationStatus.fromValue(rs.getString(STATUS)));
r.setExpiration(rs.getLong(EXPIRATION));
r.setGridIdentity(rs.getString(GRID_IDENTITY));
r.setIssuedCredentialPathLength(rs.getInt(DELEGATION_PATH_LENGTH));
ProxyLifetime lifetime = new ProxyLifetime();
lifetime.setHours(rs.getInt(PROXY_LIFETIME_HOURS));
lifetime.setMinutes(rs.getInt(PROXY_LIFETIME_MINUTES));
lifetime.setSeconds(rs.getInt(PROXY_LIFETIME_SECONDS));
r.setIssuedCredentialLifetime(lifetime);
}
rs.close();
s.close();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
this.db.releaseConnection(c);
}
try {
X509Certificate[] certs = this.keyManager.getCertificates(String.valueOf(id.getDelegationId()));
r.setCertificateChain(Utils.toCertificateChain(certs));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_LOADING_CERTIFICATE_CHAIN, e);
}
try {
PolicyHandler handler = this.findHandler(getPolicyType(id.getDelegationId()));
r.setDelegationPolicy(handler.getPolicy(id));
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_LOADING_DELEGATION_POLICY, e);
}
return r;
} else {
throw Errors.makeException(DelegationException.class, Errors.DELEGATION_RECORD_DOES_NOT_EXIST);
}
}
public synchronized DelegationIdentifier approveDelegation(String callerGridIdentity, DelegationSigningResponse res) throws CDSInternalException,
DelegationException, PermissionDeniedException {
DelegationIdentifier id = res.getDelegationIdentifier();
if (this.delegationExists(id)) {
DelegationRecord r = getDelegationRecord(id);
if (!r.getDelegationStatus().equals(DelegationStatus.PENDING)) {
throw Errors.makeException(DelegationException.class, Errors.CANNOT_APPROVE_INVALID_STATUS);
}
Calendar c = new GregorianCalendar();
c.setTimeInMillis(r.getDateInitiated());
c.add(Calendar.SECOND, DELEGATION_BUFFER_SECONDS);
Date d = new Date();
if (d.after(c.getTime())) {
throw Errors.makeException(DelegationException.class, Errors.DELEGATION_APPROVAL_BUFFER_EXPIRED);
}
// Check to make sure that the entity that initiated the delegation
// is the same entity that is approving it.
if (!r.getGridIdentity().equals(callerGridIdentity)) {
throw Errors.makeException(DelegationException.class, Errors.INITIATOR_DOES_NOT_MATCH_APPROVER);
}
CertificateChain chain = res.getCertificateChain();
if (chain == null) {
throw Errors.makeException(DelegationException.class, Errors.CERTIFICATE_CHAIN_NOT_SPECIFIED);
}
X509Certificate[] certs = null;
try {
certs = Utils.toCertificateArray(chain);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_LOADING_CERTIFICATE_CHAIN, e);
}
if (certs.length < 2) {
throw Errors.makeException(DelegationException.class, Errors.INSUFFICIENT_CERTIFICATE_CHAIN_SPECIFIED);
}
// Check that the public keys match.
java.security.PublicKey publicKey = this.keyManager.getPublicKey(String.valueOf(id.getDelegationId()));
if (!certs[0].getPublicKey().equals(publicKey)) {
throw Errors.makeException(DelegationException.class, Errors.PUBLIC_KEY_DOES_NOT_MATCH);
}
// Check delegation path length
try {
if (CertUtil.isProxy(BouncyCastleUtil.getCertificateType(certs[0]))) {
int currLength = r.getIssuedCredentialPathLength();
for (int i = 0; i < certs.length; i++) {
if (CertUtil.isProxy(BouncyCastleUtil.getCertificateType(certs[i]))) {
int delegationPathLength = CertificateExtensionsUtil.getDelegationPathLength(certs[i]);
int maxLength = delegationPathLength - 1;
if (maxLength < currLength) {
throw Errors.makeException(DelegationException.class, Errors.INSUFFICIENT_DELEGATION_PATH_LENGTH);
}
currLength = delegationPathLength;
}
}
} else {
throw Errors.makeException(DelegationException.class, Errors.CERTIFICATE_CHAIN_DOES_NOT_CONTAIN_PROXY);
}
try {
ProxyPathValidator validator = new ProxyPathValidator();
validator.validate(certs, TrustedCertificates.getDefaultTrustedCertificates().getCertificates(),
CertificateRevocationLists.getDefaultCertificateRevocationLists());
} catch (Exception e) {
log.debug(Errors.INVALID_CERTIFICATE_CHAIN, e);
throw Errors.makeException(DelegationException.class, Errors.INVALID_CERTIFICATE_CHAIN, e);
}
// Check to make sure the Identity of the proxy cert matches the
// Identity of the initiator.
try {
if (!BouncyCastleUtil.getIdentity(certs).equals(r.getGridIdentity())) {
throw Errors.makeException(DelegationException.class, Errors.IDENTITY_DOES_NOT_MATCH_INITIATOR);
}
} catch (CertificateException e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_EXTRACTING_IDENTITY_FROM_CERTIFICATE_CHAIN, e);
}
} catch (CDSInternalException e) {
throw e;
} catch (DelegationException e) {
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_DETERMINING_DELEGATION_PATH_LENGTH, e);
}
this.keyManager.storeCertificates(String.valueOf(id.getDelegationId()), certs);
Connection conn = null;
try {
Date now = new Date();
conn = this.db.getConnection();
PreparedStatement s = conn.prepareStatement("update " + TABLE + " SET " + STATUS + "=?," + EXPIRATION + "=?," + DATE_APPROVED + "=?"
+ " WHERE " + DELEGATION_ID + "= ?");
s.setString(1, DelegationStatus.APPROVED.value());
s.setLong(2, Utils.getEarliestExpiration(certs).getTime());
s.setLong(3, now.getTime());
s.setLong(4, id.getDelegationId());
s.executeUpdate();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
this.db.releaseConnection(conn);
}
logEvent(id.getDelegationId(), callerGridIdentity, DelegatedCredentialEvent.DELEGATION_APPROVED, "The delegated credential for "
+ callerGridIdentity + " has been approved.");
return id;
} else {
throw Errors.makeException(DelegationException.class, Errors.DELEGATION_RECORD_DOES_NOT_EXIST);
}
}
public void updateDelegatedCredentialStatus(String callerGridIdentity, DelegationIdentifier id, DelegationStatus status) throws CDSInternalException,
DelegationException {
if (this.delegationExists(id)) {
if (status.equals(DelegationStatus.PENDING)) {
throw Errors.makeException(DelegationException.class, Errors.CANNOT_CHANGE_STATUS_TO_PENDING);
}
DelegationRecord r = getDelegationRecord(id);
Connection conn = null;
try {
conn = this.db.getConnection();
PreparedStatement s = conn.prepareStatement("update " + TABLE + " SET " + STATUS + "=?" + " WHERE " + DELEGATION_ID + "= ?");
s.setString(1, status.value());
s.setLong(2, id.getDelegationId());
s.executeUpdate();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
this.db.releaseConnection(conn);
}
logEvent(id.getDelegationId(), callerGridIdentity, DelegatedCredentialEvent.DELEGATION_STATUS_UPDATED, "Delegation Status changed from "
+ r.getDelegationStatus().value() + " to " + status.value());
} else {
throw Errors.makeException(DelegationException.class, Errors.DELEGATION_RECORD_DOES_NOT_EXIST);
}
}
public CertificateChain getDelegatedCredential(String gridIdentity, DelegationIdentifier id, PublicKey publicKey) throws CDSInternalException,
DelegationException, PermissionDeniedException {
if (delegationExists(id)) {
DelegationRecord r = this.getDelegationRecord(id);
if (!r.getDelegationStatus().equals(DelegationStatus.APPROVED)) {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED, Errors.CANNOT_GET_INVALID_STATUS);
throw Errors.makeException(DelegationException.class, Errors.CANNOT_GET_INVALID_STATUS);
}
PolicyHandler handler = null;
try {
handler = this.findHandler(r.getDelegationPolicy().getClass().getName());
} catch (Exception e) {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED, Errors.POLICY_HANDLER_NOT_FOUND);
throw Errors.makeException(CDSInternalException.class, Errors.POLICY_HANDLER_NOT_FOUND, e);
}
if (!handler.isAuthorized(id, gridIdentity)) {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED,
Errors.PERMISSION_DENIED_TO_DELEGATED_CREDENTIAL);
throw Errors.makeException(PermissionDeniedException.class, Errors.PERMISSION_DENIED_TO_DELEGATED_CREDENTIAL);
}
Date now = new Date();
Date expiration = new Date(r.getExpiration());
if (now.after(expiration)) {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED, Errors.SIGNING_CREDENTIAL_EXPIRED);
throw Errors.makeException(DelegationException.class, Errors.SIGNING_CREDENTIAL_EXPIRED);
}
X509Certificate[] certs = null;
try {
certs = Utils.toCertificateArray(r.getCertificateChain());
} catch (Exception e) {
log.error(e.getMessage(), e);
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED,
Errors.UNEXPECTED_ERROR_LOADING_CERTIFICATE_CHAIN);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_LOADING_CERTIFICATE_CHAIN, e);
}
try {
java.security.PublicKey pkey = KeyUtil.loadPublicKey(publicKey.getKeyAsString());
int length = ((RSAPublicKey) pkey).getModulus().bitLength();
if (!this.proxyPolicy.isKeySizeSupported(length)) {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED,
Errors.INVALID_KEY_LENGTH_SPECIFIED);
throw Errors.makeException(DelegationException.class, Errors.INVALID_KEY_LENGTH_SPECIFIED);
}
int hours = 0;
int minutes = 0;
int seconds = 0;
Calendar c = new GregorianCalendar();
c.add(Calendar.HOUR_OF_DAY, r.getIssuedCredentialLifetime().getHours());
c.add(Calendar.MINUTE, r.getIssuedCredentialLifetime().getMinutes());
c.add(Calendar.SECOND, r.getIssuedCredentialLifetime().getSeconds() + PROXY_EXPIRATION_BUFFER_SECONDS);
if (c.getTime().after(certs[0].getNotAfter())) {
Calendar expires = new GregorianCalendar();
expires.setTimeInMillis(certs[0].getNotAfter().getTime());
long diff = (certs[0].getNotAfter().getTime() - System.currentTimeMillis()) / 1000;
if (diff > PROXY_EXPIRATION_BUFFER_SECONDS) {
seconds = (int) diff - PROXY_EXPIRATION_BUFFER_SECONDS;
} else {
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ACCESS_DENIED,
Errors.SIGNING_CREDENTIAL_ABOUT_EXPIRE);
throw Errors.makeException(DelegationException.class, Errors.SIGNING_CREDENTIAL_ABOUT_EXPIRE);
}
} else {
hours = r.getIssuedCredentialLifetime().getHours();
minutes = r.getIssuedCredentialLifetime().getMinutes();
seconds = r.getIssuedCredentialLifetime().getSeconds();
}
X509Certificate[] proxy = ProxyCreator.createImpersonationProxyCertificate(certs,
this.keyManager.getPrivateKey(String.valueOf(id.getDelegationId())), pkey, hours, minutes, seconds, r.getIssuedCredentialPathLength());
logEvent(id.getDelegationId(), gridIdentity, DelegatedCredentialEvent.DELEGATED_CREDENTIAL_ISSUED, "A credential was issued to " + gridIdentity
+ ". The credential will expire on " + proxy[0].getNotAfter().toString() + ".");
return Utils.toCertificateChain(proxy);
} catch (DelegationException f) {
throw f;
} catch (Exception e) {
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_ERROR_CREATING_PROXY, e);
}
} else {
throw Errors.makeException(DelegationException.class, Errors.DELEGATION_RECORD_DOES_NOT_EXIST);
}
}
public List<DelegationRecord> findDelegatedCredentials(DelegationRecordFilter f) throws CDSInternalException {
this.buildDatabase();
Connection c = null;
try {
c = this.db.getConnection();
List<DelegationRecord> records = new ArrayList<DelegationRecord>();
boolean filterAdded = false;
StringBuffer sql = new StringBuffer();
sql.append("select " + DELEGATION_ID + " from " + TABLE);
// NOTE: it appears like caGrid 1.4 (at least the gaards-ui) is sending a non-null delegationidentifier, which has a "long" that defaults to 0.
// technically I should honor the request to look for delegationId=0, but since the ids actually start at 1, this would never return anything
// anyway.
// If you pass a 0, it will behave the same as if you passed null now.
if (f.getDelegationIdentifier() != null && f.getDelegationIdentifier().getDelegationId() != 0) {
if (!filterAdded) {
sql.append(" WHERE ");
filterAdded = true;
} else {
sql.append(" AND ");
}
sql.append(DELEGATION_ID + " = ?");
}
if (f.getGridIdentity() != null && !f.getGridIdentity().trim().equals("")) {
if (!filterAdded) {
sql.append(" WHERE ");
filterAdded = true;
} else {
sql.append(" AND ");
}
sql.append(GRID_IDENTITY + " = ?");
}
if (f.getDelegationStatus() != null) {
if (!filterAdded) {
sql.append(" WHERE ");
filterAdded = true;
} else {
sql.append(" AND ");
}
sql.append(STATUS + " = ?");
}
if (f.getExpirationStatus() != null) {
if (!filterAdded) {
sql.append(" WHERE ");
filterAdded = true;
} else {
sql.append(" AND ");
}
if (f.getExpirationStatus().equals(ExpirationStatus.VALID)) {
sql.append(EXPIRATION + " > ? AND EXPIRATION>0");
} else {
sql.append(EXPIRATION + " < ? AND EXPIRATION>0");
}
}
PreparedStatement s = c.prepareStatement(sql.toString());
int count = 0;
// see NOTE above where the WHERE/AND clause is added
if (f.getDelegationIdentifier() != null && f.getDelegationIdentifier().getDelegationId() != 0) {
count = count + 1;
s.setLong(count, f.getDelegationIdentifier().getDelegationId());
}
if (f.getGridIdentity() != null && !f.getGridIdentity().trim().equals("")) {
count = count + 1;
s.setString(count, f.getGridIdentity());
}
if (f.getDelegationStatus() != null) {
count = count + 1;
s.setString(count, f.getDelegationStatus().value());
}
if (f.getExpirationStatus() != null) {
count = count + 1;
Date now = new Date();
s.setLong(count, now.getTime());
}
ResultSet rs = s.executeQuery();
while (rs.next()) {
DelegationIdentifier id = new DelegationIdentifier();
id.setDelegationId(rs.getLong(DELEGATION_ID));
records.add(getDelegationRecord(id));
}
rs.close();
s.close();
return records;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
this.db.releaseConnection(c);
}
}
private String getPolicyType(long delegationId) throws CDSInternalException {
Connection c = null;
String policyType = null;
try {
c = this.db.getConnection();
PreparedStatement s = c.prepareStatement("select " + POLICY_TYPE + " from " + TABLE + " WHERE " + DELEGATION_ID + "= ?");
s.setLong(1, delegationId);
ResultSet rs = s.executeQuery();
if (rs.next()) {
policyType = rs.getString(POLICY_TYPE);
}
rs.close();
s.close();
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
this.db.releaseConnection(c);
}
return policyType;
}
public synchronized void delete(DelegationIdentifier id) throws CDSInternalException {
this.delete(id.getDelegationId());
}
public synchronized void delete(long delegationId) throws CDSInternalException {
buildDatabase();
Connection c = null;
try {
String policyType = getPolicyType(delegationId);
PolicyHandler handler = findHandler(policyType);
c = db.getConnection();
PreparedStatement s = c.prepareStatement("DELETE FROM " + TABLE + " WHERE " + DELEGATION_ID + "= ?");
s.setLong(1, delegationId);
s.execute();
s.close();
this.keyManager.delete(String.valueOf(delegationId));
DelegationIdentifier id = new DelegationIdentifier();
id.setDelegationId(delegationId);
handler.removePolicy(id);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
} finally {
db.releaseConnection(c);
}
try {
List<Event> list = this.delegationAuditor.findEvents(String.valueOf(delegationId), null, null, null, null, null);
for (int i = 0; i < list.size(); i++) {
this.delegationAuditor.deleteEvent(list.get(i).getEventId());
}
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, "An inexpected error occurred in deleting the audit log.", e);
}
}
public void clearDatabase() throws CDSInternalException {
buildDatabase();
try {
for (int i = 0; i < handlers.size(); i++) {
this.handlers.get(i).removeAllStoredPolicies();
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
try {
this.keyManager.deleteAll();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
try {
events.clearHandlers();
} catch (Exception e) {
log.error(e.getMessage(), e);
}
try {
db.update("DELETE FROM " + TABLE);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
}
dbBuilt = false;
}
private void buildDatabase() throws CDSInternalException {
if (!dbBuilt) {
try {
if (!this.db.tableExists(TABLE)) {
String trust = "CREATE TABLE " + TABLE + " (" + DELEGATION_ID + " BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY," + GRID_IDENTITY
+ " VARCHAR(255) NOT NULL," + POLICY_TYPE + " VARCHAR(255) NOT NULL," + STATUS + " VARCHAR(50) NOT NULL," + DATE_INITIATED
+ " BIGINT," + DATE_APPROVED + " BIGINT," + DELEGATION_PATH_LENGTH + " INT," + PROXY_LIFETIME_HOURS + " INT,"
+ PROXY_LIFETIME_MINUTES + " INT," + PROXY_LIFETIME_SECONDS + " INT," + EXPIRATION + " BIGINT, INDEX document_index ("
+ DELEGATION_ID + "));";
db.update(trust);
}
dbBuilt = true;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw Errors.makeException(CDSInternalException.class, Errors.UNEXPECTED_DATABASE_ERROR, e);
}
}
}
}