All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itextpdf.signatures.validation.v1.SignatureValidationProperties Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2024 Apryse Group NV
    Authors: Apryse Software.

    This program is offered under a commercial and under the AGPL license.
    For commercial licensing, contact us at https://itextpdf.com/sales.  For AGPL licensing, see below.

    AGPL licensing:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see .
 */
package com.itextpdf.signatures.validation.v1;

import java.time.Duration;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.function.Consumer;

import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.validation.v1.context.CertificateSource;
import com.itextpdf.signatures.validation.v1.context.CertificateSources;
import com.itextpdf.signatures.validation.v1.context.TimeBasedContext;
import com.itextpdf.signatures.validation.v1.context.TimeBasedContexts;
import com.itextpdf.signatures.validation.v1.context.ValidationContext;
import com.itextpdf.signatures.validation.v1.context.ValidatorContext;
import com.itextpdf.signatures.validation.v1.context.ValidatorContexts;
import com.itextpdf.signatures.validation.v1.extensions.CertificateExtension;
import com.itextpdf.signatures.validation.v1.extensions.DynamicBasicConstraintsExtension;
import com.itextpdf.signatures.validation.v1.extensions.ExtendedKeyUsageExtension;
import com.itextpdf.signatures.validation.v1.extensions.KeyUsage;
import com.itextpdf.signatures.validation.v1.extensions.KeyUsageExtension;
import com.itextpdf.signatures.validation.v1.report.ValidationReport.ValidationResult;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

/**
 * Class which stores properties, which are related to signature validation process.
 */
public class SignatureValidationProperties {
    public static final boolean DEFAULT_CONTINUE_AFTER_FAILURE = true;
    public static final Duration DEFAULT_FRESHNESS_PRESENT_CRL = Duration.ofDays(30);
    public static final Duration DEFAULT_FRESHNESS_PRESENT_OCSP = Duration.ofDays(30);
    public static final Duration DEFAULT_FRESHNESS_HISTORICAL = Duration.ofMinutes(1);
    public static final OnlineFetching DEFAULT_ONLINE_FETCHING = OnlineFetching.FETCH_IF_NO_OTHER_DATA_AVAILABLE;

    private final HashMap properties = new HashMap<>();
    private final List ocspClients = new ArrayList<>();
    private final List crlClients = new ArrayList<>();

    /**
     * Create {@link SignatureValidationProperties} with default values.
     */
    public SignatureValidationProperties() {
        setContinueAfterFailure(ValidatorContexts.all(), CertificateSources.all(), DEFAULT_CONTINUE_AFTER_FAILURE);
        setRevocationOnlineFetching(ValidatorContexts.all(), CertificateSources.all(), TimeBasedContexts.all(),
                DEFAULT_ONLINE_FETCHING);

        setFreshness(ValidatorContexts.all(), CertificateSources.all(),
                TimeBasedContexts.of(TimeBasedContext.HISTORICAL), DEFAULT_FRESHNESS_HISTORICAL);
        setFreshness(ValidatorContexts.all(), CertificateSources.all(),
                TimeBasedContexts.of(TimeBasedContext.PRESENT), DEFAULT_FRESHNESS_PRESENT_OCSP);
        setFreshness(ValidatorContexts.of(ValidatorContext.CRL_VALIDATOR), CertificateSources.all(),
                TimeBasedContexts.of(TimeBasedContext.PRESENT), DEFAULT_FRESHNESS_PRESENT_CRL);

        setRequiredExtensions(CertificateSources.of(CertificateSource.CRL_ISSUER),
                Collections.singletonList(new KeyUsageExtension(KeyUsage.CRL_SIGN)));
        setRequiredExtensions(CertificateSources.of(CertificateSource.OCSP_ISSUER),
                Collections.singletonList(new ExtendedKeyUsageExtension(
                        Collections.singletonList(ExtendedKeyUsageExtension.OCSP_SIGNING))));
        setRequiredExtensions(CertificateSources.of(CertificateSource.SIGNER_CERT),
                Collections.singletonList(new KeyUsageExtension(KeyUsage.NON_REPUDIATION)));
        List certIssuerRequiredExtensions = new ArrayList<>();
        certIssuerRequiredExtensions.add(new KeyUsageExtension(KeyUsage.KEY_CERT_SIGN));
        certIssuerRequiredExtensions.add(new DynamicBasicConstraintsExtension());
        setRequiredExtensions(CertificateSources.of(CertificateSource.CERT_ISSUER), certIssuerRequiredExtensions);
        setRequiredExtensions(CertificateSources.of(CertificateSource.TIMESTAMP),
                Collections.singletonList(new ExtendedKeyUsageExtension(
                        Collections.singletonList(ExtendedKeyUsageExtension.TIME_STAMPING))));

        ocspClients.add(new ValidationOcspClient());
        crlClients.add(new ValidationCrlClient());
    }

    /**
     * Returns the freshness setting for the provided validation context or the default context
     * in milliseconds.
     *
     * @param validationContext the validation context for which to retrieve the freshness setting
     *
     * @return the freshness setting for the provided validation context or the default context in milliseconds
     */
    public Duration getFreshness(ValidationContext validationContext) {
        return this.getParametersValueFor(validationContext.getValidatorContext(),
                validationContext.getCertificateSource(), validationContext.getTimeBasedContext(),
                p -> p.getFreshness());
    }

    /**
     * Sets the freshness setting for the specified validator,
     * time based and certificate source contexts in milliseconds.
     * 

* This parameter specifies how old revocation data can be, compared to validation time, in order to be trustworthy. * * @param validatorContexts the validators for which to apply the setting * @param certificateSources the certificate sources to * @param timeBasedContexts the date comparison context for which to apply the setting * @param value the settings value in milliseconds * * @return this same {@link SignatureValidationProperties} instance. */ public final SignatureValidationProperties setFreshness(ValidatorContexts validatorContexts, CertificateSources certificateSources, TimeBasedContexts timeBasedContexts, Duration value) { setParameterValueFor(validatorContexts.getSet(), certificateSources.getSet(), timeBasedContexts.getSet(), p -> p.setFreshness(value)); return this; } /** * Returns the Continue after failure setting for the provided context or the default context. * * @param validationContext the context for which to retrieve the Continue after failure setting * * @return the Continue after failure setting for the provided context or the default context */ public boolean getContinueAfterFailure(ValidationContext validationContext) { return this.getParametersValueFor(validationContext.getValidatorContext(), validationContext.getCertificateSource(), validationContext.getTimeBasedContext(), p -> p.getContinueAfterFailure()); } /** * Sets the Continue after failure setting for the provided context. *

* This parameter specifies if validation is expected to continue after first failure is encountered. * Only {@link ValidationResult#INVALID} is considered to be a failure. * * @param validatorContexts the validators for which to set the Continue after failure setting * @param certificateSources the certificateSources for which to set the Continue after failure setting * @param value the Continue after failure setting * * @return this same {@link SignatureValidationProperties} instance. */ public final SignatureValidationProperties setContinueAfterFailure(ValidatorContexts validatorContexts, CertificateSources certificateSources, boolean value) { setParameterValueFor(validatorContexts.getSet(), certificateSources.getSet(), TimeBasedContexts.all().getSet(), p -> p.setContinueAfterFailure(value)); return this; } /** * Sets the onlineFetching property representing possible online fetching permissions. * * @param validationContext the context for which to retrieve the online fetching setting * * @return the online fetching setting. */ public OnlineFetching getRevocationOnlineFetching(ValidationContext validationContext) { return this.getParametersValueFor(validationContext.getValidatorContext(), validationContext.getCertificateSource(), validationContext.getTimeBasedContext(), p -> p.getOnlineFetching()); } /** * Sets the onlineFetching property representing possible online fetching permissions. * * @param validatorContexts the validators for which to set this value * @param certificateSources the certificate source for which to set this value * @param timeBasedContexts time perspective context, at which validation is happening * @param onlineFetching onlineFetching property value to set * * @return this same {@link SignatureValidationProperties} instance. */ public final SignatureValidationProperties setRevocationOnlineFetching(ValidatorContexts validatorContexts, CertificateSources certificateSources, TimeBasedContexts timeBasedContexts, OnlineFetching onlineFetching) { setParameterValueFor(validatorContexts.getSet(), certificateSources.getSet(), timeBasedContexts.getSet(), p -> p.setOnlineFetching(onlineFetching)); return this; } /** * Returns required extension for the provided validation context. * * @param validationContext the validation context for which to retrieve required extensions * * @return required extensions for the provided validation context */ public List getRequiredExtensions(ValidationContext validationContext) { return this.>getParametersValueFor(validationContext.getValidatorContext(), validationContext.getCertificateSource(), validationContext.getTimeBasedContext(), p -> p.getRequiredExtensions()); } /** * Set list of extensions which are required to be set to a certificate depending on certificate source. *

* By default, required extensions are set to be compliant with common validation norms. * Changing those can result in falsely positive validation result. * * @param certificateSources {@link CertificateSource} for extensions to be present * @param requiredExtensions list of required {@link CertificateExtension} * * @return this same {@link SignatureValidationProperties} instance */ public final SignatureValidationProperties setRequiredExtensions(CertificateSources certificateSources, List requiredExtensions) { // make a defensive copy of requiredExtensions and already wrap it with unmodifiableList so that we don't have // to do this every time it is retrieved. Now we are protected against changes in passed list and from // changes in the returned list List copy = Collections.unmodifiableList( new ArrayList<>(requiredExtensions)); setParameterValueFor(ValidatorContexts.all().getSet(), certificateSources.getSet(), TimeBasedContexts.all().getSet(), p -> p.setRequiredExtensions(copy)); return this; } /** * Gets all {@link ICrlClient} instances which will be used to retrieve CRL responses during the validation. * * @return all {@link ICrlClient} instances which will be used to retrieve CRL responses during the validation */ public List getCrlClients() { return Collections.unmodifiableList(crlClients); } /** * Adds new {@link ICrlClient} instance which will be used to retrieve CRL responses during the validation. * * @param crlClient {@link ICrlClient} instance which will be used to retrieve CRL responses during the validation * * @return this same {@link SignatureValidationProperties} instance */ public final SignatureValidationProperties addCrlClient(ICrlClient crlClient) { crlClients.add(crlClient); return this; } /** * Gets all {@link IOcspClient} instances which will be used to retrieve OCSP responses during the validation. * * @return all {@link IOcspClient} instances which will be used to retrieve OCSP responses during the validation */ public List getOcspClients() { return Collections.unmodifiableList(ocspClients); } /** * Adds new {@link IOcspClient} instance which will be used to retrieve OCSP response during the validation. * * @param ocspClient {@link IOcspClient} instance which will be used to retrieve OCSP response during the validation * * @return this same {@link SignatureValidationProperties} instance */ public final SignatureValidationProperties addOcspClient(IOcspClient ocspClient) { ocspClients.add(ocspClient); return this; } /** * This method executes the setter method for every combination of selected validators and certificateSources * * @param validatorContexts the validators to execute the setter on * @param certificateSources the certificate sources to execute the setter on * @param setter the setter to execute */ final void setParameterValueFor(EnumSet validatorContexts, EnumSet certificateSources, EnumSet timeBasedContexts, Consumer setter) { for (ValidatorContext validatorContext : validatorContexts) { for (CertificateSource certificateSource : certificateSources) { for (TimeBasedContext timeBasedContext : timeBasedContexts) { ValidationContext vc = new ValidationContext(validatorContext, certificateSource, timeBasedContext); ContextProperties cProperties = properties.computeIfAbsent(vc, unused -> new ContextProperties()); setter.accept(cProperties); } } } } /** * This method executes the getter method to the most granular parameters set down until the getter returns * a non-null value * * @param validatorContext the validator for which the value is to be retrieved * @param certSource the certificate source for which the value is to be retrieved * @param getter the getter to get the value from the parameters set * @param the type of the return value of this method and the getter method * * @return the first non-null value returned. */ T getParametersValueFor(ValidatorContext validatorContext, CertificateSource certSource, TimeBasedContext timeBasedContext, Function getter) { // all three match ValidationContext c = new ValidationContext(validatorContext, certSource, timeBasedContext); if (properties.containsKey(c)) { return getter.apply(properties.get(c)); } return null; } /** * Enum representing possible online fetching permissions. */ public enum OnlineFetching { /** * Permission to always fetch revocation data online. */ ALWAYS_FETCH, /** * Permission to fetch revocation data online if no other revocation data available. */ FETCH_IF_NO_OTHER_DATA_AVAILABLE, /** * Forbids fetching revocation data online. */ NEVER_FETCH } static class ContextProperties { private Duration freshness; private Boolean continueAfterFailure; private OnlineFetching onlineFetching; private List requiredExtensions; public ContextProperties() { // Empty constructor. } public Boolean getContinueAfterFailure() { return continueAfterFailure; } public void setContinueAfterFailure(Boolean continueAfterFailure) { this.continueAfterFailure = continueAfterFailure; } public Duration getFreshness() { return freshness; } public void setFreshness(Duration value) { freshness = value; } public OnlineFetching getOnlineFetching() { return onlineFetching; } public void setOnlineFetching(OnlineFetching onlineFetching) { this.onlineFetching = onlineFetching; } public List getRequiredExtensions() { return requiredExtensions; } public void setRequiredExtensions(List requiredExtensions) { this.requiredExtensions = requiredExtensions; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy