1

I've been trawling the internet for a good 24 hours and just can't find a resolution that works.

I have a schema file that contains an import line:

<xsd:import namespace="http://www.w3.org/2000/09/xmldsig#" 
            schemaLocation=
              "http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/xmldsig-core-schema.xsd"/>

Here is my code to validate the Xml:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(null, @"C:\TEMP\myschema.xsd");

XmlReader xmlReader = XmlReader.Create(new StringReader(document.InnerXml), settings);
while (xmlReader.Read()) { }

When I run it I get: The 'http://www.w3.org/2000/09/xmldsig#:Signature' element is not declared.

If I change my code (as suggested by searches) to:

settings.ValidationType = ValidationType.DTD;
settings.DtdProcessing = DtdProcessing.Parse;

Then I receive no error but the validation doesn't work as there is I have deliberately inserted an invalid value to test that the validation is working.

I've tried adding the schema being imported directly:

settings.Schemas.Add(null, @"C:\TEMP\xmldsig-core-schema.xsd");

But receieve the error: For security reasons DTD is prohibited in this XML document. To enable DTD processing...

I've tried every combination of XmlReaderSettings settings I can think of and that have been suggested by searches.

I'm really just proper stumped now.

C. M. Sperberg-McQueen
  • 24,596
  • 5
  • 38
  • 65
David
  • 1,731
  • 24
  • 37

3 Answers3

5

Ok managed to figure it out. Was staring me in the face the whole time.

When I tried to add the xmldsig-core-schema.xsd schema to the XmlReaderSettings I got the following message:

For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method.

The following code is what was needed:

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;

settings.Schemas.Add(null, @"C:\TEMP\myschema.xsd");

// Create new XmlReaderSettings with DtdProcessing set to Parse.
XmlReaderSettings settings2 = new XmlReaderSettings();
settings2.DtdProcessing = DtdProcessing.Parse;

// Create an XmlReader passing it the location of the problematic xsd and the new XmlReaderSettings.
XmlReader reader = XmlReader.Create(@"C:\TEMP\xmldsig-core-schema.xsd", settings2);

// Add the reader to the first XmlReaderSettings
settings.Schemas.Add(null, reader);

I think there is probably a more eloquent and succinct way to write that code but I've spent so long on it I'm just happy it works. If anyone wants to edit it feel free.

Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
David
  • 1,731
  • 24
  • 37
  • 2
    After spending 3-4 hours trying to figure out the "DTD prohibited error", this is what solved my problem. I just also set **settings.MaxCharactersFromEntities = 1024;** because of [this](https://stackoverflow.com/questions/3451203/how-does-the-billion-laughs-xml-dos-attack-work). Thanks for posting this..!!! – skamble89 Jan 15 '20 at 13:10
  • 2
    Spot on - solved my problem! A gem of an answer, especially since it was posted 7+ years ago ;-) – Caad9Rider Oct 27 '20 at 14:48
1

You wrote:

When I run it I get: The http://www.w3.org/2000/09/xmldsig#:Signature element is not declared.

Looks like it just cannot load that imported schema by that URL: http://www.w3.org/TR/2001/PR-xmldsig-core-20010820/xmldsig-core-schema.xsd

I've checked that URL and the schema does exist there, as well as the element {http://www.w3.org/2000/09/xmldsig#}Signature is declared in it (globally).

But it takes rather long time to load that schema, apparently because W3C discourages (and actually hinders) the huge traffic to their XML resources from numerous software around the globe.

Concerning this:

But receieve the error: For security reasons DTD is prohibited in this XML document. To enable DTD processing...

I am not sure which programming system you use (Java, .NET etc), but it comes down to its settings, which may be passed to it either via your code or some config file(s) or environment variables.

That schema does include a reference to some DTD (XMLSchema.dtd) that must be loaded:

<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" 
                        "http://www.w3.org/2001/XMLSchema.dtd" [
  <!ATTLIST schema xmlns:ds CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#'>
  <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
  <!ENTITY % p ''>
  <!ENTITY % s ''>
]>

I suggest you also to load that DTD from that URL: http://www.w3.org/2001/XMLSchema.dtd and place it in the same directory as the schema. Then, edit the schema file and change the DTD location to be the same (as schema):

<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "XMLSchema.dtd" [
....

... and also http://www.w3.org/2001/datatypes.dtd will be required locally as it is referenced from XMLSchema.dtd.

ColdFusion
  • 2,381
  • 13
  • 14
  • Thanks for the reply. I've copied those files (XMLSchema.dtd & datatypes.dtd) and changed the references but still getting the same problem. The xmldsig schema is just to validate the signed the xml, if I remove the import line and the "Session" element from the xsd then the validation works for the rest of the document. This is ultra frustrating. I'm using C#/.Net by the way. – David Jul 04 '13 at 13:05
  • Then it comes down to .NET and I'm not professional in it. It is more about .NET security stuff rather than XML schemas... read docs, method/property descriptions etc. – ColdFusion Jul 04 '13 at 13:21
1

An easy way to skip this validation was commenting the first lines (DTD part) on xmldsig-core-schema.xsd

<!--<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd" [
   <!ATTLIST schema 
     xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
   <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
   <!ENTITY % p ''>
   <!ENTITY % s ''>
  ]>-->
default
  • 551
  • 8
  • 16