package at.gv.egovernment.moa.spss.server.invoke;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import iaik.IAIKException;
import iaik.IAIKRuntimeException;
import iaik.server.modules.cmsverify.CMSSignatureVerificationModule;
import iaik.server.modules.cmsverify.CMSSignatureVerificationModuleFactory;
import iaik.server.modules.cmsverify.CMSSignatureVerificationProfile;
import iaik.server.modules.cmsverify.CMSSignatureVerificationResult;
import at.gv.egovernment.moa.logging.LoggingContext;
import at.gv.egovernment.moa.logging.LoggingContextManager;
import at.gv.egovernment.moa.spss.MOAApplicationException;
import at.gv.egovernment.moa.spss.MOAException;
import at.gv.egovernment.moa.spss.api.cmsverify.CMSContent;
import at.gv.egovernment.moa.spss.api.cmsverify.CMSContentExcplicit;
import at.gv.egovernment.moa.spss.api.cmsverify.CMSContentReference;
import at.gv.egovernment.moa.spss.api.cmsverify.CMSDataObject;
import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest;
import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse;
import at.gv.egovernment.moa.spss.server.logging.IaikLog;
import at.gv.egovernment.moa.spss.server.logging.TransactionId;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContext;
import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager;
/**
* A class providing an interface to the
* CMSSignatureVerificationModule
.
*
* This class performs the invocation of the
* iaik.server.modules.cmsverify.CMSSignatureVerificationModule
* from a VerifyCMSSignatureRequest
. The result of the invocation
* is integrated into a VerifyCMSSignatureResponse
returned.
*
* @author Patrick Peck
* @version $Id$
*/
public class CMSSignatureVerificationInvoker {
/** The single instance of this class. */
private static CMSSignatureVerificationInvoker instance = null;
/**
* Return the only instance of this class.
*
* @return The only instance of this class.
*/
public static synchronized CMSSignatureVerificationInvoker getInstance() {
if (instance == null) {
instance = new CMSSignatureVerificationInvoker();
}
return instance;
}
/**
* Create a new CMSSignatureVerificationInvoker
.
*
* Protected to disallow multiple instances.
*/
protected CMSSignatureVerificationInvoker() {
}
/**
* Verify a CMS signature.
*
* @param request The VerifyCMSSignatureRequest
containing the
* CMS signature, as well as additional data needed for verification.
* @return Element A VerifyCMSSignatureResponse
containing the
* answer to the VerifyCMSSignatureRequest
.
* @throws MOAException An error occurred while processing the request.
*/
public VerifyCMSSignatureResponse verifyCMSSignature(VerifyCMSSignatureRequest request)
throws MOAException {
CMSSignatureVerificationProfileFactory profileFactory =
new CMSSignatureVerificationProfileFactory(request);
VerifyCMSSignatureResponseBuilder responseBuilder =
new VerifyCMSSignatureResponseBuilder();
TransactionContext context =
TransactionContextManager.getInstance().getTransactionContext();
LoggingContext loggingCtx =
LoggingContextManager.getInstance().getLoggingContext();
InputStream signature;
InputStream signedContent = null;
CMSSignatureVerificationProfile profile;
Date signingTime;
List results;
CMSSignatureVerificationResult result;
int[] signatories;
InputStream input;
byte[] buf = new byte[256];
// get the signature
signature = request.getCMSSignature();
try {
// get the signed content
signedContent = getSignedContent(request);
// build the profile
profile = profileFactory.createProfile();
// get the signing time
signingTime = request.getDateTime();
// verify the signature
CMSSignatureVerificationModule module =
CMSSignatureVerificationModuleFactory.getInstance();
module.setLog(new IaikLog(loggingCtx.getNodeID()));
module.init(
signature,
signedContent,
profile,
new TransactionId(context.getTransactionID()));
input = module.getInputStream();
while (input.read(buf) > 0);
results = module.verifySignature(signingTime);
} catch (IAIKException e) {
MOAException moaException = IaikExceptionMapper.getInstance().map(e);
throw moaException;
} catch (IAIKRuntimeException e) {
MOAException moaException = IaikExceptionMapper.getInstance().map(e);
throw moaException;
} catch (IOException e) {
throw new MOAApplicationException("2244", null, e);
} catch (MOAException e)
{
throw e;
}
finally
{
try
{
if (signedContent != null) signedContent.close();
}
catch (Throwable t)
{
// Intentionally do nothing here
}
}
// build the response: for each signatory add the result to the response
signatories = request.getSignatories();
if (signatories == VerifyCMSSignatureRequest.ALL_SIGNATORIES) {
Iterator resultIter;
for (resultIter = results.iterator(); resultIter.hasNext();) {
result = (CMSSignatureVerificationResult) resultIter.next();
responseBuilder.addResult(result);
}
} else {
int i;
for (i = 0; i < signatories.length; i++) {
int sigIndex = signatories[i] - 1;
try {
result =
(CMSSignatureVerificationResult) results.get(signatories[i] - 1);
responseBuilder.addResult(result);
} catch (IndexOutOfBoundsException e) {
throw new MOAApplicationException(
"2249",
new Object[] { new Integer(sigIndex)});
}
}
}
return responseBuilder.getResponse();
}
/**
* Get the signed content contained either in the request itself or given as a
* reference to external data.
*
* @param request The VerifyCMSSignatureRequest
containing the
* signed content (or the reference to the signed content).
* @return InputStream A stream providing the signed content data, or
* null
if no signed content was provided with the request.
* @throws MOAApplicationException An error occurred building the stream.
*/
private InputStream getSignedContent(VerifyCMSSignatureRequest request)
throws MOAApplicationException {
CMSDataObject dataObj;
CMSContent content;
// select the Content element
dataObj = request.getDataObject();
if (dataObj == null) {
return null;
}
content = dataObj.getContent();
// build the content data
switch (content.getContentType()) {
case CMSContent.EXPLICIT_CONTENT :
return ((CMSContentExcplicit) content).getBinaryContent();
case CMSContent.REFERENCE_CONTENT :
String reference = ((CMSContentReference) content).getReference();
if (!"".equals(reference)) {
ExternalURIResolver resolver = new ExternalURIResolver();
return resolver.resolve(reference);
} else {
return null;
}
default :
return null;
}
}
}