Skip to content

Commit

Permalink
Add validation of xsd and xslt hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
Bombino1024 committed Jun 30, 2023
1 parent 76a78db commit f80b752
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 16 deletions.
46 changes: 46 additions & 0 deletions src/main/java/digital/slovensko/autogram/core/XDCTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Base64;

public class XDCTransformer {

public enum DestinationMediaType {
TXT, HTML, XHTML
}
Expand Down Expand Up @@ -70,6 +71,19 @@ private XDCTransformer(String identifier, String xsdSchema, String xsltSchema, S
this.mediaDestinationTypeDescription = mediaDestinationTypeDescription;
}

public XDCTransformer(String xsdSchema, String xsltSchema, String canonicalizationMethod,
DigestAlgorithm digestAlgorithm, Document document) {
this.xsdSchema = xsdSchema;
this.xsltSchema = xsltSchema;
this.canonicalizationMethod = canonicalizationMethod;
this.digestAlgorithm = digestAlgorithm;
this.identifierUri = null;
this.identifierVersion = null;
this.containerXmlns = null;
this.mediaDestinationTypeDescription = null;
this.document = document;
}

public DSSDocument transform(DSSDocument dssDocument) {
try {
var xmlByteArrayInput = dssDocument.openStream().readAllBytes();
Expand Down Expand Up @@ -230,4 +244,36 @@ public static DOMSource extractFromXDC(Document document, DocumentBuilderFactory

return new DOMSource(document);
}

private String getDigestValueFromElement(String elementLocalName) {
var xdc = document.getDocumentElement();

var xmlData = xdc.getElementsByTagNameNS("http://data.gov.sk/def/container/xmldatacontainer+xml/1.1", elementLocalName)
.item(0);
if (xmlData == null)
throw new RuntimeException("XMLData not found in XDC");

var attributes = xmlData.getAttributes();
if (attributes == null)
throw new RuntimeException("Attributes not found");

var digestValue = attributes.getNamedItem("DigestValue");
if (digestValue == null)
throw new RuntimeException("DigestValue not found");

return digestValue.getNodeValue();
}

public boolean validateXsd() {
String xsdSchemaHash = computeDigest(xsdSchema);
String xsdDigestValue = getDigestValueFromElement("UsedXSDReference");
return xsdSchemaHash.equals(xsdDigestValue);
}

public boolean validateXslt() {
String xsltSchemaHash = computeDigest(xsltSchema);
String xsltDigestValue = getDigestValueFromElement("UsedPresentationSchemaReference");
return xsltSchemaHash.equals(xsltDigestValue);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
Expand Down Expand Up @@ -64,16 +65,59 @@ public SigningParameters getParameters() throws RequestValidationException {
parameters.validate(getDocument().getMimeType());

SigningParameters signingParameters = parameters.getSigningParameters(isBase64());

if (!validateXml(getXmlContent(), signingParameters.getSchema()))
throw new RequestValidationException("XML validation against XSD failed", "");

validateXml(signingParameters);

return signingParameters;
}

private String getXmlContent() {
boolean isXdc = getDocument().getMimeType().equals(AutogramMimeType.XML_DATACONTAINER);
return isXdc ? getContentFromXdc() : getDecodedContent();
private boolean isBase64() {
return payloadMimeType.contains("base64");
}

private void validateXml(SigningParameters signingParameters) {
String xsdSchema = signingParameters.getSchema();
String xmlContent;

if (isXdc()) {
if (!validateXsdAndXsltHashes(signingParameters)) {
throw new RequestValidationException("XML validation failed", "Invalid xsd scheme or xslt transformation");
}

xmlContent = getContentFromXdc();
if (xmlContent == null) {
throw new RequestValidationException("XML validation failed", "Unable to get content from xdc container");
}
} else {
xmlContent = getDecodedContent();
}

if (!validateXmlContentAgainstXsd(xmlContent, xsdSchema)) {
throw new RequestValidationException("XML validation failed", "XML validation against XSD failed");
}
}

private boolean isXdc() {
return getDocument().getMimeType().equals(AutogramMimeType.XML_DATACONTAINER);
}

private boolean validateXsdAndXsltHashes(SigningParameters sp) {
try {
var builderFactory = DocumentBuilderFactory.newInstance();
builderFactory.setNamespaceAware(true);

XDCTransformer xdcTransformer = new XDCTransformer(
sp.getSchema(),
sp.getTransformation(),
sp.getPropertiesCanonicalization(),
sp.getDigestAlgorithm(),
builderFactory.newDocumentBuilder().parse(new InputSource(getDocument().openStream()))
);

return xdcTransformer.validateXsd() && xdcTransformer.validateXslt();
} catch (Exception e) {
return false;
}
}

private String getContentFromXdc() {
Expand All @@ -84,7 +128,7 @@ private String getContentFromXdc() {
var element = XDCTransformer.extractFromXDC(document, builderFactory);
return transformElementToString(element);
} catch (Exception e) {
throw new RequestValidationException("Unable to get XML content from XDC container", "");
return null;
}
}

Expand All @@ -97,7 +141,11 @@ private static String transformElementToString(DOMSource element) throws Transfo
return writer.toString();
}

private boolean validateXml(String xmlContent, String xsdSchema) {
private String getDecodedContent() {
return isBase64() ? new String(Base64.getDecoder().decode(document.getContent())) : document.getContent();
}

private boolean validateXmlContentAgainstXsd(String xmlContent, String xsdSchema) {
if (xsdSchema == null) {
return true;
}
Expand All @@ -111,12 +159,4 @@ private boolean validateXml(String xmlContent, String xsdSchema) {
return false;
}
}

private boolean isBase64() {
return payloadMimeType.contains("base64");
}

private String getDecodedContent() {
return isBase64() ? new String(Base64.getDecoder().decode(document.getContent())) : document.getContent();
}
}

0 comments on commit f80b752

Please sign in to comment.