/*
* DSS - Digital Signature Services
*
* Copyright (C) 2013 European Commission, Directorate-General Internal Market and Services (DG MARKT), B-1049 Bruxelles/Brussel
*
* Developed by: 2013 ARHS Developments S.A. (rue Nicolas Bové 2B, L-1253 Luxembourg) http://www.arhs-developments.com
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* "DSS - Digital Signature Services" 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 2.1 of the
* License, or (at your option) any later version.
*
* DSS 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
* "DSS - Digital Signature Services". If not, see <http://www.gnu.org/licenses/>.
*/
package eu.europa.ec.markt.dss.validation102853.policy;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import eu.europa.ec.markt.dss.DSSUtils;
import eu.europa.ec.markt.dss.exception.DSSException;
import eu.europa.ec.markt.dss.validation102853.RuleUtils;
import eu.europa.ec.markt.dss.validation102853.xml.XmlDom;
/**
* This class encapsulates the constraint file that controls the policy to be used during the validation process. It
* adds the functions to direct access to the file data. It is the implementation of the ETSI 102853 standard.
*
* @author bielecro
*/
public class EtsiValidationPolicy extends ValidationPolicy {
protected static final String TRUE = "true";
protected static final String FALSE = "false";
private long maxRevocationFreshnessString;
private String maxRevocationFreshnessUnit;
private Long maxRevocationFreshness;
private Long timestampDelayTime;
private Map<String, Date> algorithmExpirationDate = new HashMap<String, Date>();
public EtsiValidationPolicy(Document document) {
super(document);
}
@Override
public boolean isRevocationFreshnessToBeChecked() {
return null != getElement("/ConstraintsParameters/Revocation/RevocationFreshness/");
}
@Override
public String getFormatedMaxRevocationFreshness() {
if (maxRevocationFreshness == null) {
getMaxRevocationFreshness();
}
return maxRevocationFreshnessString + " " + maxRevocationFreshnessUnit;
}
@Override
public Long getMaxRevocationFreshness() {
if (maxRevocationFreshness == null) {
maxRevocationFreshness = Long.MAX_VALUE;
final XmlDom revocationFreshness = getElement("/ConstraintsParameters/Revocation/RevocationFreshness");
if (revocationFreshness != null) {
maxRevocationFreshnessString = getLongValue("/ConstraintsParameters/Revocation/RevocationFreshness/text()");
maxRevocationFreshnessUnit = getValue("/ConstraintsParameters/Revocation/RevocationFreshness/@Unit");
maxRevocationFreshness = RuleUtils.convertDuration(maxRevocationFreshnessUnit, "MILLISECONDS", maxRevocationFreshnessString);
if (maxRevocationFreshness == 0) {
maxRevocationFreshness = Long.MAX_VALUE;
}
}
}
return maxRevocationFreshness;
}
@Override
public Date getAlgorithmExpirationDate(final String algorithm) {
Date date = algorithmExpirationDate.get(algorithm);
if (date == null) {
final XmlDom algoExpirationDateDom = getElement("/ConstraintsParameters/Timestamp/Cryptographic/AlgoExpirationDate");
if (algoExpirationDateDom == null) {
return null;
}
String expirationDateFormat = algoExpirationDateDom.getValue("./@Format");
if (expirationDateFormat.isEmpty()) {
expirationDateFormat = "yyyy-MM-dd";
}
final String expirationDateString = algoExpirationDateDom.getValue("./Algo[@Name='%s']/text()", algorithm);
if (expirationDateString.isEmpty()) {
throw new DSSException(String.format("The the expiration date is not defined for '%s' algorithm!", algorithm));
}
date = DSSUtils.parseDate(expirationDateFormat, expirationDateString);
algorithmExpirationDate.put(algorithm, date);
}
return date;
}
@Override
public SignaturePolicyConstraint getSignaturePolicyConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/AcceptablePolicies/@Level");
if (DSSUtils.isNotBlank(level)) {
final SignaturePolicyConstraint constraint = new SignaturePolicyConstraint(level);
final List<XmlDom> policyList = getElements("/ConstraintsParameters/MainSignature/AcceptablePolicies/Id");
final List<String> identifierList = XmlDom.convertToStringList(policyList);
constraint.setIdentifiers(identifierList);
constraint.setExpectedValue(identifierList.toString());
return constraint;
}
return null;
}
@Override
public Constraint getStructuralValidationConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/StructuralValidation";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningTimeConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/SigningTime";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getContentTypeConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentType";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getContentHintsConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentHints";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getContentIdentifierConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentIdentifier";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getCommitmentTypeIndicationConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/CommitmentTypeIndication/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
final List<XmlDom> commitmentTypeIndications = getElements("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/CommitmentTypeIndication/Identifier");
final List<String> identifierList = XmlDom.convertToStringList(commitmentTypeIndications);
constraint.setExpectedValue(identifierList.toString());
constraint.setIdentifiers(identifierList);
return constraint;
}
return null;
}
@Override
public Constraint getSignerLocationConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/SignerLocation/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
return constraint;
}
return null;
}
@Override
public Constraint getContentTimestampPresenceConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentTimestamp/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
return constraint;
}
return null;
}
@Override
public Constraint getClaimedRoleConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ClaimedRoles/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
final List<XmlDom> claimedRoles = getElements("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ClaimedRoles/Role");
final List<String> claimedRoleList = XmlDom.convertToStringList(claimedRoles);
constraint.setExpectedValue(claimedRoleList.toString());
constraint.setIdentifiers(claimedRoleList);
return constraint;
}
return null;
}
@Override
public List<String> getClaimedRoles() {
final List<XmlDom> list = getElements("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ClaimedRoles/Role");
final List<String> claimedRoles = XmlDom.convertToStringList(list);
return claimedRoles;
}
@Override
public boolean shouldCheckIfCertifiedRoleIsPresent() {
final long count = getCountValue("count(/ConstraintsParameters/MainSignature/MandatedSignedQProperties/CertifiedRoles/Role)");
return count > 0;
}
@Override
public List<String> getCertifiedRoles() {
final List<XmlDom> list = getElements("/ConstraintsParameters/MainSignature/MandatedSignedQProperties/CertifiedRoles/Role");
final List<String> claimedRoles = XmlDom.convertToStringList(list);
return claimedRoles;
}
@Override
public String getPolicyName() {
final String policy = getValue("/ConstraintsParameters/@Name");
return policy;
}
@Override
public String getPolicyDescription() {
final String description = getValue("/ConstraintsParameters/Description/text()");
return description;
}
@Override
public Long getTimestampDelayTime() {
if (timestampDelayTime == null) {
final XmlDom timestampDelayPresent = getElement("/ConstraintsParameters/Timestamp/TimestampDelay");
if (timestampDelayPresent == null) {
return null;
}
final long timestampDelay = getLongValue("/ConstraintsParameters/Timestamp/TimestampDelay/text()");
final String timestampUnit = getValue("/ConstraintsParameters/Timestamp/TimestampDelay/@Unit");
timestampDelayTime = RuleUtils.convertDuration(timestampUnit, "MILLISECONDS", timestampDelay);
}
return timestampDelayTime;
}
@Override
public String getCertifiedRolesAttendance() {
String attendance = getValue("ConstraintsParameters/MainSignature/MandatedSignedQProperties/ClaimedRoles/@Attendance");
return attendance;
}
@Override
public SignatureCryptographicConstraint getSignatureCryptographicConstraint(final String context) {
final String rootXPathQuery = String.format("/ConstraintsParameters/%s/Cryptographic", context);
return getSignatureCryptographicConstraint_(rootXPathQuery, context, null);
}
@Override
public SignatureCryptographicConstraint getSignatureCryptographicConstraint(final String context, final String subContext) {
final String rootXPathQuery = String.format("/ConstraintsParameters/%s/%s/Cryptographic", context, subContext);
return getSignatureCryptographicConstraint_(rootXPathQuery, context, subContext);
}
@Override
protected SignatureCryptographicConstraint getSignatureCryptographicConstraint_(final String rootXPathQuery, final String context, final String subContext) {
final String level = getValue(rootXPathQuery + "/@Level");
if (DSSUtils.isNotBlank(level)) {
final SignatureCryptographicConstraint constraint = new SignatureCryptographicConstraint(level, context, subContext);
final List<XmlDom> encryptionAlgoList = getElements(rootXPathQuery + "/AcceptableEncryptionAlgo/Algo");
final List<String> encryptionAlgoStringList = XmlDom.convertToStringList(encryptionAlgoList);
constraint.setEncryptionAlgorithms(encryptionAlgoStringList);
final List<XmlDom> digestAlgoList = getElements(rootXPathQuery + "/AcceptableDigestAlgo/Algo");
final List<String> digestAlgoStringList = XmlDom.convertToStringList(digestAlgoList);
constraint.setDigestAlgorithms(digestAlgoStringList);
final List<XmlDom> miniPublicKeySizeList = getElements(rootXPathQuery + "/MiniPublicKeySize/Algo");
final Map<String, String> miniPublicKeySizeStringMap = XmlDom.convertToStringMap(miniPublicKeySizeList, SIZE);
constraint.setMinimumPublicKeySizes(miniPublicKeySizeStringMap);
final List<XmlDom> algoExpirationDateList = getElements("/ConstraintsParameters/Cryptographic/AlgoExpirationDate/Algo");
final Map<String, Date> algoExpirationDateStringMap = XmlDom.convertToStringDateMap(algoExpirationDateList, DATE);
constraint.setAlgorithmExpirationDates(algoExpirationDateStringMap);
return constraint;
}
return null;
}
@Override
public Constraint getSigningCertificateKeyUsageConstraint(final String context) {
final String level = getValue("/ConstraintsParameters/%s/SigningCertificate/KeyUsage/@Level", context);
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
final List<XmlDom> keyUsages = getElements("/ConstraintsParameters/%s/SigningCertificate/KeyUsage/Identifier", context);
final List<String> identifierList = XmlDom.convertToStringList(keyUsages);
constraint.setExpectedValue(identifierList.toString());
constraint.setIdentifiers(identifierList);
return constraint;
}
return null;
}
@Override
public CertificateExpirationConstraint getSigningCertificateExpirationConstraint(final String context, final String subContext) {
final String level = getValue(String.format("/ConstraintsParameters/%s/%s/Expiration/@Level", context, subContext));
if (DSSUtils.isNotBlank(level)) {
final CertificateExpirationConstraint constraint = new CertificateExpirationConstraint(level);
return constraint;
}
return null;
}
@Override
public Constraint getProspectiveCertificateChainConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/ProspectiveCertificateChain", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getCertificateSignatureConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/Signature", context, subContext);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getRevocationDataAvailableConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/RevocationDataAvailable", context, subContext);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getRevocationDataIsTrustedConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/RevocationDataIsTrusted", context, subContext);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getRevocationDataFreshnessConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/RevocationDataFreshness", context, subContext);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateRevokedConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/Revoked", context, subContext);
return getBasicConstraint(XP_ROOT, false);
}
@Override
public Constraint getSigningCertificateOnHoldConstraint(final String context, final String subContext) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/%s/OnHold", context, subContext);
return getBasicConstraint(XP_ROOT, false);
}
@Override
public Constraint getSigningCertificateTSLValidityConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/TSLValidity", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateTSLStatusConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/TSLStatus", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateTSLStatusAndValidityConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/TSLStatusAndValidity", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getIntermediateCertificateRevokedConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/CACertificate/Revoked", context);
return getBasicConstraint(XP_ROOT, false);
}
@Override
public Constraint getChainConstraint() {
final String level = getValue("/ConstraintsParameters/MainSignature/CertificateChain/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
return constraint;
}
return null;
}
@Override
public Constraint getSigningCertificateQualificationConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/SigningCertificate/Qualification";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateSupportedBySSCDConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/SigningCertificate/SupportedBySSCD";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateIssuedToLegalPersonConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/SigningCertificate/IssuedToLegalPerson";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateRecognitionConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/Recognition", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateSignedConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/Signed", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateAttributePresentConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/AttributePresent", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateDigestValuePresentConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/DigestValuePresent", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateDigestValueMatchConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/DigestValueMatch", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateIssuerSerialMatchConstraint(final String context) {
final String XP_ROOT = String.format("/ConstraintsParameters/%s/SigningCertificate/IssuerSerialMatch", context);
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getReferenceDataExistenceConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/ReferenceDataExistence";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getReferenceDataIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/ReferenceDataIntact";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSignatureIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/SignatureIntact";
return getBasicConstraint(XP_ROOT, true);
}
@Override
protected Constraint getBasicConstraint(final String XP_ROOT, final boolean defaultExpectedValue) {
final String level = getValue(XP_ROOT + "/@Level");
if (DSSUtils.isNotBlank(level)) {
final Constraint constraint = new Constraint(level);
String expectedValue = getValue(XP_ROOT + "/text()");
if (DSSUtils.isBlank(expectedValue)) {
expectedValue = defaultExpectedValue ? TRUE : FALSE;
}
constraint.setExpectedValue(expectedValue);
return constraint;
}
return null;
}
@Override
public BasicValidationProcessValidConstraint getBasicValidationProcessConclusionConstraint() {
final BasicValidationProcessValidConstraint constraint = new BasicValidationProcessValidConstraint("FAIL");
constraint.setExpectedValue(TRUE);
return constraint;
}
@Override
public Constraint getMessageImprintDataFoundConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/MessageImprintDataFound";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getMessageImprintDataIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/MessageImprintDataIntact";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public TimestampValidationProcessValidConstraint getTimestampValidationProcessConstraint() {
final TimestampValidationProcessValidConstraint constraint = new TimestampValidationProcessValidConstraint("FAIL");
constraint.setExpectedValue(TRUE);
return constraint;
}
@Override
public Constraint getRevocationTimeConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/RevocationTimeAgainstBestSignatureTime";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getBestSignatureTimeBeforeIssuanceDateOfSigningCertificateConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/BestSignatureTimeBeforeIssuanceDateOfSigningCertificate";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getSigningCertificateValidityAtBestSignatureTimeConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/SigningCertificateValidityAtBestSignatureTime";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getAlgorithmReliableAtBestSignatureTimeConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/AlgorithmReliableAtBestSignatureTime";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getTimestampCoherenceConstraint() {
final String XP_ROOT = "/ConstraintsParameters/Timestamp/Coherence";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getTimestampDelaySigningTimePropertyConstraint() {
final Long timestampDelay = getTimestampDelayTime();
if (timestampDelay != null && timestampDelay > 0) {
final Constraint constraint = new Constraint("FAIL");
constraint.setExpectedValue(TRUE);
return constraint;
}
return null;
}
@Override
public Constraint getContentTimestampImprintIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentTimestamp/MessageImprintDataIntact";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getContentTimestampImprintFoundConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedSignedQProperties/ContentTimestamp/MessageImprintDataFound";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getCounterSignatureReferenceDataExistenceConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedUnsignedQProperties/CounterSignature/ReferenceDataExistence";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getCounterSignatureReferenceDataIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedUnsignedQProperties/CounterSignature/ReferenceDataIntact";
return getBasicConstraint(XP_ROOT, true);
}
@Override
public Constraint getCounterSignatureIntactConstraint() {
final String XP_ROOT = "/ConstraintsParameters/MainSignature/MandatedUnsignedQProperties/CounterSignature/SignatureIntact";
return getBasicConstraint(XP_ROOT, true);
}
}