aboutsummaryrefslogtreecommitdiff
path: root/spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java
diff options
context:
space:
mode:
Diffstat (limited to 'spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java')
-rw-r--r--spss.server/src/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java317
1 files changed, 317 insertions, 0 deletions
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 <code>VerifyXMLSignatureResponse</code> object.
+ *
+ * <p>Via a call to <code>addResult()</code> the only result of the
+ * signature verification must be added.</p>
+ *
+ * <p>The <code>getResponseElement()</code> method then returns the
+ * <code>VerifyXMLSignatureResponse</code> built so far.</p>
+ *
+ * @author Patrick Peck
+ * @version $Id$
+ */
+public class VerifyXMLSignatureResponseBuilder {
+ /** The <code>SPSSFactory</code> 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 <code>VerifyMLSignatureResponse</code> built so far.
+ *
+ * @return The <code>VerifyXMLSignatureResponse</code> 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
+ * <code>VerifyXMLSignatureResponse</code>.
+ *
+ * @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 <code>Content</code> object from the given <code>DataObject</code>.
+ *
+ * @param dataObject The <code>DataObject</code> from which to build the
+ * <code>Content</code>. Based on the type of this parameter, the type of
+ * <code>Content</code> will either be <code>XML_CONTENT</code> or
+ * <code>BINARY_CONTENT</code>.
+ * @return The <code>Content</code> 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 <code>isHashValid()</code>
+ * method returns <code>false</code>.
+ *
+ * @param refInfos A <code>List</code> containing the
+ * <code>ReferenceInfo</code> 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;
+ }
+ }
+
+}