From ece7d18cf35374bf4e26d041799cda8f791c89f8 Mon Sep 17 00:00:00 2001 From: gregor Date: Mon, 7 Jul 2003 10:58:37 +0000 Subject: Initial commit git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@2 d688527b-c9ab-4aba-bd8d-4036d912da1d --- .../invoke/VerifyXMLSignatureResponseBuilder.java | 317 +++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java (limited to 'spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java') diff --git a/spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java b/spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java new file mode 100644 index 000000000..2f55261d1 --- /dev/null +++ b/spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java @@ -0,0 +1,317 @@ +package at.gv.egovernment.moa.spss.server.invoke; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.NodeList; + +import iaik.ixsil.algorithms.CanonicalizationAlgorithm; +import iaik.ixsil.algorithms.CanonicalizationAlgorithmImplExclusiveCanonicalXMLWithComments; +import iaik.server.modules.xml.BinaryDataObject; +import iaik.server.modules.xml.DataObject; +import iaik.server.modules.xml.XMLDataObject; +import iaik.server.modules.xml.XMLNodeListDataObject; +import iaik.server.modules.xmlverify.CertificateValidationResult; +import iaik.server.modules.xmlverify.DsigManifest; +import iaik.server.modules.xmlverify.HashUnavailableException; +import iaik.server.modules.xmlverify.ReferenceData; +import iaik.server.modules.xmlverify.ReferenceInfo; +import iaik.server.modules.xmlverify.SecurityLayerManifest; +import iaik.server.modules.xmlverify.XMLSignatureVerificationProfile; +import iaik.server.modules.xmlverify.XMLSignatureVerificationResult; +import iaik.x509.X509Certificate; + +import at.gv.egovernment.moa.util.CollectionUtils; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.NodeListAdapter; + +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.api.SPSSFactory; +import at.gv.egovernment.moa.spss.api.common.CheckResult; +import at.gv.egovernment.moa.spss.api.common.Content; +import at.gv.egovernment.moa.spss.api.common.SignerInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.ManifestRefsCheckResultInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.ReferencesCheckResult; +import at.gv.egovernment.moa.spss.api.xmlverify.ReferencesCheckResultInfo; +import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; + +/** + * A class to build a VerifyXMLSignatureResponse object. + * + *

Via a call to addResult() the only result of the + * signature verification must be added.

+ * + *

The getResponseElement() method then returns the + * VerifyXMLSignatureResponse built so far.

+ * + * @author Patrick Peck + * @version $Id$ + */ +public class VerifyXMLSignatureResponseBuilder { + /** The SPSSFactory for creating API objects. */ + private SPSSFactory factory = SPSSFactory.getInstance(); + + /** Information about the signer certificate. */ + private SignerInfo signerInfo; + /** The hash input data. */ + private List hashInputDatas; + /** The reference input data. */ + private List referenceInputDatas; + /** The result of the signature check. */ + private ReferencesCheckResult signatureCheck; + /** The result of the signature manifest check. */ + private ReferencesCheckResult signatureManifestCheck; + /** The result of the XMLDsig manifest check. */ + private List xmlDsigManifestChecks; + /** The result of the certificate check. */ + private CheckResult certificateCheck; + + /** + * Get the VerifyMLSignatureResponse built so far. + * + * @return The VerifyXMLSignatureResponse built so far. + */ + public VerifyXMLSignatureResponse getResponse() { + return factory.createVerifyXMLSignatureResponse( + signerInfo, + hashInputDatas, + referenceInputDatas, + signatureCheck, + signatureManifestCheck, + xmlDsigManifestChecks, + certificateCheck); + } + + /** + * Sets the verification result to the response. + * + * This method must be called exactly once to ensure a valid + * VerifyXMLSignatureResponse. + * + * @param result The result to set for the response. + * @param profile The profile used for verifying the signature. + * @throws MOAApplicationException An error occurred adding the result. + */ + public void setResult( + XMLSignatureVerificationResult result, + XMLSignatureVerificationProfile profile, + ReferencesCheckResult transformsSignatureManifestCheck) + throws MOAApplicationException { + + CertificateValidationResult certResult = + result.getCertificateValidationResult(); + List referenceDataList; + ReferenceData referenceData; + List dsigManifestList; + ReferencesCheckResultInfo checkResultInfo; + int[] failedReferences; + Iterator iter; + + // create the SignerInfo; + signerInfo = + factory.createSignerInfo( + (X509Certificate) certResult.getCertificateChain().get(0), + certResult.isQualifiedCertificate(), + certResult.isPublicAuthorityCertificate(), + certResult.getPublicAuthorityID()); + + // add HashInputData Content objects + referenceDataList = result.getReferenceDataList(); + if (profile.includeHashInputData()) { + hashInputDatas = new ArrayList(); + for (iter = referenceDataList.iterator(); iter.hasNext();) { + referenceData = (ReferenceData) iter.next(); + hashInputDatas.add(buildContent(referenceData.getHashInputData())); + } + } + + // create the ReferenceInputData Content objects + if (profile.includeReferenceInputData()) { + referenceInputDatas = new ArrayList(); + for (iter = referenceDataList.iterator(); iter.hasNext();) { + referenceData = (ReferenceData) iter.next(); + referenceInputDatas.add( + buildContent(referenceData.getReferenceInputData())); + } + } + + // create the signature check + failedReferences = buildFailedReferences(result.getReferenceDataList()); + checkResultInfo = + failedReferences != null + ? factory.createReferencesCheckResultInfo(null, failedReferences) + : null; + signatureCheck = + factory.createReferencesCheckResult( + result.getSignatureValueVerificationCode().intValue(), + checkResultInfo); + + // create the signature manifest check + if (profile.checkSecurityLayerManifest()) { + if (transformsSignatureManifestCheck.getCode() == 1) { + // checking the transforms failed + signatureManifestCheck = transformsSignatureManifestCheck; + } else if (!result.containsSecurityLayerManifest()) { + // no security layer manifest in signature + signatureManifestCheck = factory.createReferencesCheckResult(2, null); + } else { + // other error codes provided by IAIK signature verification + // need to add 1 to the check code for MOA compatibility + SecurityLayerManifest slManifest = result.getSecurityLayerManifest(); + int verificationResult = + slManifest.getManifestVerificationResult().intValue(); + + switch (verificationResult) { + case 0 : + signatureManifestCheck = + factory.createReferencesCheckResult(0, null); + break; + case 2 : + case 3 : + failedReferences = + buildFailedReferences(slManifest.getReferenceInfoList()); + checkResultInfo = + failedReferences != null + ? factory.createReferencesCheckResultInfo(null, failedReferences) + : null; + signatureManifestCheck = + factory.createReferencesCheckResult( + verificationResult + 1, + checkResultInfo); + } + } + + // Code = 1 prüfen + + if (result.containsSecurityLayerManifest()) { + } else { + // SignatureManifestCheck Code = 2 + } + } + + // create the xmlDsigManifestCheck + if (profile.checkXMLDsigManifests()) { + xmlDsigManifestChecks = new ArrayList(); + dsigManifestList = result.getDsigManifestList(); + for (iter = dsigManifestList.iterator(); iter.hasNext();) { + DsigManifest dsigManifest = (DsigManifest) iter.next(); + int refIndex = + dsigManifest.getReferringReferenceInfo().getReferenceIndex(); + ManifestRefsCheckResultInfo manifestCheckResultInfo; + + failedReferences = + buildFailedReferences(dsigManifest.getReferenceInfoList()); + manifestCheckResultInfo = + factory.createManifestRefsCheckResultInfo( + null, + failedReferences, + refIndex); + xmlDsigManifestChecks.add( + factory.createManifestRefsCheckResult( + dsigManifest.getManifestVerificationResult().intValue(), + manifestCheckResultInfo)); + } + } + + // create the certificate check + certificateCheck = + factory.createCheckResult( + certResult.getValidationResultCode().intValue(), + null); + } + + /** + * Build a Content object from the given DataObject. + * + * @param dataObject The DataObject from which to build the + * Content. Based on the type of this parameter, the type of + * Content will either be XML_CONTENT or + * BINARY_CONTENT. + * @return The Content object containing the data. + * @throws MOAApplicationException An error occurred adding the content. + */ + private Content buildContent(DataObject dataObject) + throws MOAApplicationException { + + if (dataObject instanceof BinaryDataObject) { + BinaryDataObject binaryData = (BinaryDataObject) dataObject; + return factory.createContent(binaryData.getInputStream(), null); + } else if (dataObject instanceof XMLDataObject) { + XMLDataObject xmlData = (XMLDataObject) dataObject; + List nodes = new ArrayList(); + + nodes.add(xmlData.getElement()); + return factory.createContent(new NodeListAdapter(nodes), null); + } else { // dataObject instanceof XMLNodeListDataObject + // if the data in the NodeList can be converted back to valid XML, + // write it as XMLContent; otherwise, write it as Base64Content + XMLNodeListDataObject nodeData = (XMLNodeListDataObject) dataObject; + NodeList nodes = nodeData.getNodeList(); + + if (DOMUtils.checkAttributeParentsInNodeList(nodes)) { + // insert as XMLContent + try { + DocumentFragment fragment = DOMUtils.nodeList2DocumentFragment(nodes); + + return factory.createContent(fragment.getChildNodes(), null); + } catch (Exception e) { + // not successful -> fall through to the Base64Content + } + } + + // insert canonicalized NodeList as binary content + try { + CanonicalizationAlgorithm c14n = + new CanonicalizationAlgorithmImplExclusiveCanonicalXMLWithComments(); + InputStream is; + + c14n.setInput(nodes); + is = c14n.canonicalize(); + return factory.createContent(is, null); + } catch (Exception e) { + throw new MOAApplicationException("2200", null); + } + } + } + + /** + * Build the failed references. + * + * Failed references are references for which the isHashValid() + * method returns false. + * + * @param refInfos A List containing the + * ReferenceInfo objects to be checked. + * @return The indexes of the failed references. + */ + private int[] buildFailedReferences(List refInfos) { + List failedReferencesList = new ArrayList(); + int i; + + // find out the failed references + for (i = 0; i < refInfos.size(); i++) { + ReferenceInfo refInfo = (ReferenceInfo) refInfos.get(i); + + try { + if (refInfo.isHashCalculated() && !refInfo.isHashValid()) { + failedReferencesList.add(new Integer(i + 1)); + } + } catch (HashUnavailableException e) { + // nothing to do here because we called refInfo.isHashCalculated first + } + } + + // convert to an int array + if (failedReferencesList.isEmpty()) { + return null; + } else { + int[] failedReferences = CollectionUtils.toIntArray(failedReferencesList); + + return failedReferences; + } + } + +} -- cgit v1.2.3