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; } } }