/* * XAdES4j - A Java library for generation and verification of XAdES signatures. * Copyright (C) 2010 Luis Goncalves. * * XAdES4j is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 3 of the License, or any later version. * * XAdES4j is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License along * with XAdES4j. If not, see <http://www.gnu.org/licenses/>. */ package xades4j.verification; import java.math.BigInteger; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.security.auth.x500.X500Principal; import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial; import org.apache.xml.security.signature.ObjectContainer; import org.apache.xml.security.signature.XMLSignature; import org.apache.xml.security.signature.XMLSignatureInput; import org.apache.xml.security.utils.resolver.ResourceResolver; import org.apache.xml.security.utils.resolver.ResourceResolverException; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * The context available during the verification of the qualifying properties. * @see QualifyingPropertyVerifier * @author Luís */ public class QualifyingPropertyVerificationContext { private final XMLSignature signature; private final CertificationChainData certChainData; private final SignedObjectsData signedObjectsData; QualifyingPropertyVerificationContext( XMLSignature signature, CertificationChainData certChainData, SignedObjectsData signedObjectsData) { this.signature = signature; this.certChainData = certChainData; this.signedObjectsData = signedObjectsData; } public XMLSignature getSignature() { return signature; } public CertificationChainData getCertChainData() { return certChainData; } public SignedObjectsData getSignedObjectsData() { return signedObjectsData; } /** * */ public static class CertificationChainData { private final List<X509Certificate> certificateChain; private final Collection<X509CRL> crls; private final X500Principal validationCertIssuer; private final BigInteger validationCertSerialNumber; CertificationChainData( List<X509Certificate> certificateChain, Collection<X509CRL> crls, XMLX509IssuerSerial validationCertIssuerSerial) { this.certificateChain = Collections.unmodifiableList(certificateChain); this.crls = Collections.unmodifiableCollection(crls); if (validationCertIssuerSerial != null) { this.validationCertIssuer = new X500Principal(validationCertIssuerSerial.getIssuerName()); this.validationCertSerialNumber = validationCertIssuerSerial.getSerialNumber(); } else { validationCertIssuer = null; validationCertSerialNumber = null; } } public List<X509Certificate> getCertificateChain() { return certificateChain; } public Collection<X509CRL> getCrls() { return crls; } public X500Principal getValidationCertIssuer() { return validationCertIssuer; } public BigInteger getValidationCertSerialNumber() { return validationCertSerialNumber; } } /** * The find methods assume that object references are same-document references. * The references are resolved using the ResourceResolver of Apache XML Security, * which means the supported types of references (short-name XPointer, XPath) * depend on the configured resolvers. Fragments and short-name XPointers are * supported by the default configuration. */ public static class SignedObjectsData { private final List<RawDataObjectDesc> dataObjs; private final Map<Element, RawDataObjectDesc> references; private final Map<Element, ObjectContainer> objects; private final Document signatureDoc; SignedObjectsData( List<RawDataObjectDesc> references, XMLSignature signature) { this.dataObjs = references; this.signatureDoc = signature.getDocument(); // Map elements to References. this.references = new HashMap<Element, RawDataObjectDesc>(references.size()); for (RawDataObjectDesc obj : references) { this.references.put(obj.getReference().getElement(), obj); } // Map elements to XMLObjects. int nXmlObjs = signature.getObjectLength(); this.objects = new HashMap<Element, ObjectContainer>(nXmlObjs); for (int i = 0; i < nXmlObjs; i++) { ObjectContainer xmlObj = signature.getObjectItem(i); this.objects.put(xmlObj.getElement(), xmlObj); } } /** * In signature order. */ public List<RawDataObjectDesc> getAllDataObjects() { return dataObjs; } public RawDataObjectDesc findSignedDataObject(String objReference) { return getReferencedElement(objReference, this.references); } public ObjectContainer findXMLObject(String objReference) { return getReferencedElement(objReference, this.objects); } private <TObj> TObj getReferencedElement( String objReference, Map<Element, TObj> mapper) { if (!objReference.startsWith("#")) throw new IllegalArgumentException(); if (mapper.isEmpty()) return null; // A little workaround to be able to use the ResourceResolver. Attr refAttr = this.signatureDoc.createAttributeNS(null, "ref"); refAttr.setNodeValue(objReference); this.signatureDoc.createElementNS(null, "dummy").setAttributeNodeNS(refAttr); try { XMLSignatureInput refData = ResourceResolver.getInstance(refAttr, "", true).resolve(refAttr, "", true); // This has to be a NodeSet data because it is a same-document reference. Node refNode = refData.getSubNode(); if (refNode.getNodeType() != Node.ELEMENT_NODE) return null; // May return null. return mapper.get((Element)refNode); } catch (ResourceResolverException ex) { // Maybe an exception should be thrown... return null; } } } }