Skip to content

Commit

Permalink
Added certificate revocation check on signing certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Jan 8, 2024
1 parent e9ebcc6 commit 93c0895
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@
public final class Phase4PeppolServletConfiguration
{
public static final boolean DEFAULT_RECEIVER_CHECK_ENABLED = true;
public static final boolean DEFAULT_CHECK_SIGNING_CERTIFICATE_REVOCATION = true;

private static final Logger LOGGER = LoggerFactory.getLogger (Phase4PeppolServletConfiguration.class);

private static boolean s_bReceiverCheckEnabled = DEFAULT_RECEIVER_CHECK_ENABLED;
private static ISMPServiceMetadataProvider s_aSMPClient;
private static String s_sAS4EndpointURL;
private static X509Certificate s_aAPCertificate;
private static boolean s_bPerformSBDHValueChecks = PeppolSBDHDocumentReader.DEFAULT_PERFORM_VALUE_CHECKS;
private static boolean s_bCheckSigningCertificateRevocation = DEFAULT_CHECK_SIGNING_CERTIFICATE_REVOCATION;

private Phase4PeppolServletConfiguration ()
{}
Expand Down Expand Up @@ -184,20 +187,49 @@ public static boolean isPerformSBDHValueChecks ()
/**
* Enable or disable the SBDH value checks. By default checks are enabled.
*
* @param bPerformSBDHValueChecks
* @param b
* <code>true</code> to enable the checks, <code>false</code> to
* disable them
* @since 0.12.1
*/
public static void setPerformSBDHValueChecks (final boolean bPerformSBDHValueChecks)
public static void setPerformSBDHValueChecks (final boolean b)
{
final boolean bChange = b != s_bPerformSBDHValueChecks;
s_bPerformSBDHValueChecks = b;
if (bChange)
{
LOGGER.info (CAS4.LIB_NAME + " Peppol SBDH value checks are now " + (b ? "enabled" : "disabled"));
}
}

/**
* @return <code>true</code> if the signing certificate should be checked for
* revocation, <code>false</code> if not.
* @since 2.7.1
*/
public static boolean isCheckSigningCertificateRevocation ()
{
return s_bCheckSigningCertificateRevocation;
}

/**
* Set whether the signing certificate should be checked for revocation or
* not.
*
* @param b
* <code>true</code> to check, <code>false</code> to disable the check
* (not recommended).
* @since 2.7.1
*/
public static void setCheckSigningCertificateRevocation (final boolean b)
{
final boolean bChange = bPerformSBDHValueChecks != s_bPerformSBDHValueChecks;
s_bPerformSBDHValueChecks = bPerformSBDHValueChecks;
final boolean bChange = b != s_bCheckSigningCertificateRevocation;
s_bCheckSigningCertificateRevocation = b;
if (bChange)
{
LOGGER.info (CAS4.LIB_NAME +
" Peppol SBDH value checks are now " +
(bPerformSBDHValueChecks ? "enabled" : "disabled"));
" Peppol signing certificate revocation check is now " +
(b ? "enabled" : "disabled"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@
import com.helger.commons.io.stream.NonBlockingByteArrayOutputStream;
import com.helger.commons.io.stream.StreamHelper;
import com.helger.commons.lang.ServiceLoaderHelper;
import com.helger.commons.state.ETriState;
import com.helger.commons.string.StringHelper;
import com.helger.jaxb.validation.WrappedCollectingValidationEventHandler;
import com.helger.peppol.sbdh.PeppolSBDHData;
import com.helger.peppol.sbdh.read.PeppolSBDHDocumentReadException;
import com.helger.peppol.sbdh.read.PeppolSBDHDocumentReader;
import com.helger.peppol.smp.ESMPTransportProfile;
import com.helger.peppol.smp.ISMPTransportProfile;
import com.helger.peppol.utils.EPeppolCertificateCheckResult;
import com.helger.peppol.utils.PeppolCertificateChecker;
import com.helger.peppol.utils.PeppolCertificateHelper;
import com.helger.peppolid.IDocumentTypeIdentifier;
import com.helger.peppolid.IParticipantIdentifier;
Expand All @@ -73,6 +76,7 @@
import com.helger.phase4.ebms3header.Ebms3UserMessage;
import com.helger.phase4.error.EEbmsError;
import com.helger.phase4.messaging.IAS4IncomingMessageMetadata;
import com.helger.phase4.mgr.MetaAS4Manager;
import com.helger.phase4.model.pmode.IPMode;
import com.helger.phase4.servlet.IAS4MessageState;
import com.helger.phase4.servlet.spi.AS4MessageProcessorResult;
Expand Down Expand Up @@ -158,11 +162,13 @@ public StandardBusinessDocument standardBusinessDocument ()
}

public static final ESMPTransportProfile DEFAULT_TRANSPORT_PROFILE = ESMPTransportProfile.TRANSPORT_PROFILE_PEPPOL_AS4_V2;

private static final Logger LOGGER = LoggerFactory.getLogger (Phase4PeppolServletMessageProcessorSPI.class);

private ICommonsList <IPhase4PeppolIncomingSBDHandlerSPI> m_aHandlers;
private ISMPTransportProfile m_aTransportProfile = DEFAULT_TRANSPORT_PROFILE;
private Phase4PeppolReceiverCheckData m_aReceiverCheckData;
private ETriState m_eCheckSigningCertificateRevocation = ETriState.UNDEFINED;

/**
* Constructor. Uses all SPI implementations of
Expand Down Expand Up @@ -256,6 +262,41 @@ public final Phase4PeppolServletMessageProcessorSPI setReceiverCheckData (@Nulla
return this;
}

/**
* @return Whether the X.509 certificate used for signing the message should
* be check for revocation or not. By default it is "UNDEFINED"
* meaning, that the global setting is used instead. May not be
* <code>null</code>.
* @since 2.7.1
* @see Phase4PeppolServletConfiguration#isCheckSigningCertificateRevocation()
* for the global setting
*/
@Nonnull
public final ETriState getCheckSigningCertificateRevocation ()
{
return m_eCheckSigningCertificateRevocation;
}

/**
* Set whether the signing X.509 certificate should be checked for revocation
* or not.
*
* @param eCheckSigningCertificateRevocation
* The signing certificate revocation state. May not be
* <code>null</code>.
* @return this for chaining
* @since 2.7.1
* @see Phase4PeppolServletConfiguration#setCheckSigningCertificateRevocation(boolean)
* to set this globally
*/
@Nonnull
public final Phase4PeppolServletMessageProcessorSPI setCheckSigningCertificateRevocation (@Nonnull final ETriState eCheckSigningCertificateRevocation)
{
ValueEnforcer.notNull (eCheckSigningCertificateRevocation, "CheckSigningCertificateRevocation");
m_eCheckSigningCertificateRevocation = eCheckSigningCertificateRevocation;
return this;
}

@Nullable
private EndpointType _getReceiverEndpoint (@Nonnull final String sLogPrefix,
@Nonnull final ISMPServiceMetadataProvider aSMPClient,
Expand Down Expand Up @@ -549,6 +590,34 @@ public AS4MessageProcessorResult processAS4UserMessage (@Nonnull final IAS4Incom
return AS4MessageProcessorResult.createFailure ();
}

// Check if signing certificate is revoked
if (m_eCheckSigningCertificateRevocation.getAsBooleanValue (Phase4PeppolServletConfiguration.isCheckSigningCertificateRevocation ()))
{
final OffsetDateTime aNow = MetaAS4Manager.getTimestampMgr ().getCurrentDateTime ();
final X509Certificate aSenderCert = aState.getUsedCertificate ();
final EPeppolCertificateCheckResult eCertCheckResult = PeppolCertificateChecker.checkPeppolAPCertificate (aSenderCert,
aNow,
ETriState.UNDEFINED,
null);
if (eCertCheckResult.isInvalid ())
{
final String sDetails = "The received Peppol message is signed with a Peppol AP certificate invalid at " +
aNow +
". Rejecting incoming message. Reason: " +
eCertCheckResult.getReason ();
LOGGER.error (sLogPrefix + sDetails);
aProcessingErrorMessages.add (EEbmsError.EBMS_FAILED_AUTHENTICATION.errorBuilder (aDisplayLocale)
.refToMessageInError (sMessageID)
.errorDetail (sDetails)
.build ());
return AS4MessageProcessorResult.createFailure ();
}
}
else
{
LOGGER.warn (sLogPrefix + "The revocation check of the received signing certificate is disabled.");
}

// Read all attachments
final ICommonsList <ReadAttachment> aReadAttachments = new CommonsArrayList <> ();
if (aIncomingAttachments != null)
Expand Down

0 comments on commit 93c0895

Please sign in to comment.