Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ public static IAS4IncomingMessageState processEbmsMessage (@NonNull @WillNotClos
{
final ErrorList aErrorList = new ErrorList ();
aValidator.validatePMode (aPMode, aErrorList, EAS4ProfileValidationMode.USER_MESSAGE);
aValidator.validateSoapMessage (aSoapDocument, aIncomingState.getSoapVersion(), aErrorList);
aValidator.validateUserMessage (aEbmsUserMessage, aErrorList);
aValidator.validateInitiatorIdentity (aEbmsUserMessage,
aIncomingState.getSigningCertificate (),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.security.cert.X509Certificate;
import java.util.EnumSet;

import com.helger.phase4.model.ESoapVersion;
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

Expand All @@ -29,6 +30,7 @@
import com.helger.phase4.ebms3header.Ebms3UserMessage;
import com.helger.phase4.incoming.IAS4IncomingMessageMetadata;
import com.helger.phase4.model.pmode.IPMode;
import org.w3c.dom.Document;

/**
* Generic AS4 profile validator
Expand Down Expand Up @@ -137,7 +139,20 @@ default void validateInitiatorIdentity (@NonNull final Ebms3UserMessage aUserMsg
{}

/**
* Validation a UserMessage
* Validation of a SoapDocument
*
* @param aSoapDocument
* The SOAP document to be validated. May not be <code>null</code>.
* @param eSoapVersion
* The SOAP version of the document to be validated.
* @param aErrorList
* The error list to be filled. May not be <code>null</code>.
*/
default void validateSoapMessage (@NonNull final Document aSoapDocument, @NonNull ESoapVersion eSoapVersion, @NonNull final ErrorList aErrorList)
{}

/**
* Validation of a UserMessage
*
* @param aUserMsg
* The message to be validated. May not be <code>null</code>.
Expand All @@ -148,7 +163,7 @@ default void validateUserMessage (@NonNull final Ebms3UserMessage aUserMsg, @Non
{}

/**
* Validation a SignalMessage
* Validation of a SignalMessage
*
* @param aSignalMsg
* The message to be validated. May not be <code>null</code>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
package com.helger.phase4.profile.bdew;

import java.security.cert.X509Certificate;
import java.util.EnumSet;

import com.helger.xml.XMLHelper;
import org.bouncycastle.asn1.x500.RDN;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.style.BCStyle;
Expand Down Expand Up @@ -63,6 +65,9 @@
import com.helger.phase4.model.pmode.leg.PModeLegSecurity;
import com.helger.phase4.profile.IAS4ProfileValidator;
import com.helger.phase4.wss.EWSSVersion;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
* Validate certain requirements imposed by the BDEW project.
Expand Down Expand Up @@ -518,10 +523,58 @@ public void validateInitiatorIdentity (@NonNull final Ebms3UserMessage aUserMsg,
}
}

@Override
public void validateSoapMessage(@NonNull Document aSoapDocument, @NonNull ESoapVersion eSoapVersion, @NonNull ErrorList aErrorList)
{
ValueEnforcer.notNull (aSoapDocument, "SoapDocument");
ValueEnforcer.notNull (aErrorList, "SoapVersion");
ValueEnforcer.notNull (aErrorList, "ErrorList");

final Element aEnvelope = aSoapDocument.getDocumentElement ();
if (aEnvelope == null)
{
aErrorList.add (_createError ("SOAP Envelope is missing"));
return;
}

Element aBodyElement = XMLHelper.getFirstChildElementOfName (aEnvelope,
eSoapVersion.getNamespaceURI (),
eSoapVersion.getBodyElementName ());

if (aBodyElement == null)
{
aErrorList.add (_createError ("SOAP Body is missing"));
return;
}

if (!_isSoapBodyEmpty (aBodyElement))
aErrorList.add (_createError ("SOAP Body must be empty"));
}

private static boolean _isSoapBodyEmpty (@NonNull final Element aBodyElement)
{
for (Node aChild = aBodyElement.getFirstChild (); aChild != null; aChild = aChild.getNextSibling ())
switch (aChild.getNodeType ())
{
case Node.ELEMENT_NODE:
return false;
case Node.TEXT_NODE, Node.CDATA_SECTION_NODE:
final String sNodeValue = aChild.getNodeValue ();
if (sNodeValue != null && !sNodeValue.trim ().isEmpty ())
return false;
break;
default:
// Ignore comments and processing instructions
break;
}
return true;
}

@Override
public void validateUserMessage (@NonNull final Ebms3UserMessage aUserMsg, @NonNull final ErrorList aErrorList)
{
ValueEnforcer.notNull (aUserMsg, "UserMsg");
ValueEnforcer.notNull (aErrorList, "ErrorList");

if (aUserMsg.getMessageInfo () == null)
{
Expand Down Expand Up @@ -637,6 +690,7 @@ public void validateUserMessage (@NonNull final Ebms3UserMessage aUserMsg, @NonN
public void validateSignalMessage (@NonNull final Ebms3SignalMessage aSignalMsg, @NonNull final ErrorList aErrorList)
{
ValueEnforcer.notNull (aSignalMsg, "SignalMsg");
ValueEnforcer.notNull (aErrorList, "ErrorList");

if (aSignalMsg.getMessageInfo () == null)
{
Expand All @@ -648,4 +702,9 @@ public void validateSignalMessage (@NonNull final Ebms3SignalMessage aSignalMsg,
aErrorList.add (_createError ("MessageInfo/MessageId is missing"));
}
}

@Override
public @NonNull EnumSet<ESignedPart> getRequiredSignedParts(boolean bMessageHasAttachments) {
return EnumSet.of(ESignedPart.EBMS_MESSAGING, ESignedPart.ATTACHMENTS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package com.helger.phase4.profile.bdew;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
Expand All @@ -29,6 +30,7 @@
import java.util.Locale;
import java.util.UUID;

import com.helger.xml.serialize.read.DOMReader;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Before;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -69,6 +71,7 @@
import com.helger.phase4.profile.IAS4ProfileValidator.EAS4ProfileValidationMode;
import com.helger.phase4.wss.EWSSVersion;
import com.helger.photon.app.mock.PhotonAppWebTestRule;
import org.w3c.dom.Document;

/**
* All essentials need to be set and need to be not null since they are getting
Expand Down Expand Up @@ -632,6 +635,35 @@ public void testValidatePModeCorrect ()
assertTrue (m_aErrorList.isEmpty ());
}

@Test
public void testValidateSoapDocumentHasEmptyBody ()
{
final Document aSoapDoc = DOMReader.readXMLDOM ("""
<S12:Envelope xmlns:S12='http://www.w3.org/2003/05/soap-envelope'>
<S12:Header/>
<S12:Body> </S12:Body>
</S12:Envelope>""");
assertNotNull (aSoapDoc);

VALIDATOR.validateSoapMessage (aSoapDoc, ESoapVersion.SOAP_12, m_aErrorList);
assertTrue (m_aErrorList.isEmpty ());
}

@Test
public void testValidateSoapDocumentHasPayloadInBody ()
{
final Document aSoapDoc = DOMReader.readXMLDOM ("""
<S12:Envelope xmlns:S12='http://www.w3.org/2003/05/soap-envelope'>
<S12:Header/>
<S12:Body><payload/></S12:Body>
</S12:Envelope>""");
assertNotNull (aSoapDoc);

VALIDATOR.validateSoapMessage (aSoapDoc, ESoapVersion.SOAP_12, m_aErrorList);
assertFalse (m_aErrorList.isEmpty ());
assertTrue (m_aErrorList.containsAny (x -> x.getErrorText (LOCALE).contains ("SOAP Body must be empty")));
}

@Test
public void testValidateUserMessageNoMessageInfo ()
{
Expand Down
Loading