@Override
public XMLSecEvent processNextEvent(InputProcessorChain inputProcessorChain)
throws XMLStreamException, XMLSecurityException {
//buffer all events until the end of the security header
final InputProcessorChain subInputProcessorChain = inputProcessorChain.createSubChain(this);
final InternalSecurityHeaderBufferProcessor internalSecurityHeaderBufferProcessor
= new InternalSecurityHeaderBufferProcessor(getSecurityProperties());
subInputProcessorChain.addProcessor(internalSecurityHeaderBufferProcessor);
boolean responsibleSecurityHeaderFound = false;
boolean timestampFound = false;
XMLSecEvent xmlSecEvent;
do {
subInputProcessorChain.reset();
xmlSecEvent = subInputProcessorChain.processHeaderEvent();
switch (xmlSecEvent.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
int documentLevel = xmlSecStartElement.getDocumentLevel();
if (documentLevel == 1) {
if (WSSUtils.getSOAPMessageVersionNamespace(xmlSecStartElement) == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "notASOAPMessage");
}
} else if (documentLevel == 3
&& xmlSecStartElement.getName().equals(WSSConstants.TAG_wsse_Security)
&& WSSUtils.isInSOAPHeader(xmlSecStartElement)) {
if (!WSSUtils.isResponsibleActorOrRole(xmlSecStartElement,
((WSSSecurityProperties) getSecurityProperties()).getActor())) {
continue;
}
responsibleSecurityHeaderFound = true;
} else if (documentLevel == 4 && responsibleSecurityHeaderFound
&& WSSUtils.isInSecurityHeader(xmlSecStartElement,
((WSSSecurityProperties) getSecurityProperties()).getActor())) {
startIndexForProcessor = xmlSecEventList.size() - 1;
//special handling for EncryptedData in the SecurityHeader. This way, if for example
// a token was encrypted we have the possibility to decrypt it before so that we
// are able to engage the appropriate processor for the token.
if (WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecStartElement.getName())) {
engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
xmlSecEventList, startIndexForProcessor, xmlSecStartElement.getName());
}
} else if (documentLevel == 5 && responsibleSecurityHeaderFound
&& WSSUtils.isInSecurityHeader(xmlSecStartElement,
((WSSSecurityProperties) getSecurityProperties()).getActor())
&& WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecStartElement.getName())) {
startIndexForProcessor = xmlSecEventList.size() - 1;
// Same goes as per EncryptedData above. This is when a child of a security header
// element is encrypted (e.g. EncryptedAssertion)
engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
xmlSecEventList, startIndexForProcessor, xmlSecStartElement.getName());
}
break;
case XMLStreamConstants.END_ELEMENT:
XMLSecEndElement xmlSecEndElement = xmlSecEvent.asEndElement();
documentLevel = xmlSecEndElement.getDocumentLevel();
if (documentLevel == 3 && responsibleSecurityHeaderFound
&& xmlSecEndElement.getName().equals(WSSConstants.TAG_wsse_Security)) {
return finalizeHeaderProcessing(
inputProcessorChain, subInputProcessorChain,
internalSecurityHeaderBufferProcessor, xmlSecEventList);
} else if (documentLevel == 4 && responsibleSecurityHeaderFound
&& WSSUtils.isInSecurityHeader(xmlSecEndElement,
((WSSSecurityProperties) getSecurityProperties()).getActor())) {
//we are in the security header and the depth is +1, so every child
//element should have a responsible handler with the exception of an EncryptedData SecurityHeader
//which is already handled in the above StartElement logic (@see comment above).
if (!WSSConstants.TAG_xenc_EncryptedData.equals(xmlSecEndElement.getName())) {
engageSecurityHeaderHandler(subInputProcessorChain, getSecurityProperties(),
xmlSecEventList, startIndexForProcessor, xmlSecEndElement.getName());
}
// Check for multiple timestamps
if (xmlSecEndElement.getName().equals(WSSConstants.TAG_wsu_Timestamp)) {
if (timestampFound) {
WSInboundSecurityContext context =
(WSInboundSecurityContext)subInputProcessorChain.getSecurityContext();
context.handleBSPRule(BSPRule.R3227);
}
timestampFound = true;
}
}