Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EDMX validation fails over DTD #3030

Open
zehavibarak opened this issue Aug 7, 2024 · 4 comments
Open

EDMX validation fails over DTD #3030

zehavibarak opened this issue Aug 7, 2024 · 4 comments
Assignees

Comments

@zehavibarak
Copy link

zehavibarak commented Aug 7, 2024

OData fails to parse EDM xml from remote endpoint due to DTD namespace.

Assemblies affected

Microsoft.OData.Client

Reproduce steps

Add xmlns:sap="http://www.sap.com/Protocols/SAPData" to a working EDM.

Expected result

HTTP OK 200.

Actual result

Exception:

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

Additional detail

Possible resolution is for DataServiceContext to accept options and pass ProhibitDtd or DtdProcessing to XML parser.

@zehavibarak zehavibarak changed the title EDMX validation fails for DTD EDMX validation fails over DTD Aug 7, 2024
@zehavibarak
Copy link
Author

zehavibarak commented Aug 7, 2024

See CsdlReader.

   // We do not allow DTDs - this is the default
    settings.DtdProcessing = DtdProcessing.Prohibit;

@gathogojr
Copy link
Contributor

gathogojr commented Aug 13, 2024

Thank you @zehavibarak for reporting this issue. We will investigate and decide the way forward.

In the meantime, a workaround you use to unblock yourself is to edit the auto-generated file and pass XmlReaderSettings parameter to the XmlReader.Create method. There are two methods you may need to modify:

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "#VersionNumber#")]
private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse)
{
    var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit /* Or whichever DtdProcessing option works for your scenario */ };
    return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse), xmlReaderSettings);
}

[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "#VersionNumber#")]
private static global::System.Xml.XmlReader CreateXmlReader()
{
    try
    {
        var assembly = global::System.Reflection.Assembly.GetExecutingAssembly();
        var resourcePath = global::System.Linq.Enumerable.Single(assembly.GetManifestResourceNames(), str => str.EndsWith(filePath));
        global::System.IO.Stream stream = assembly.GetManifestResourceStream(resourcePath);
        var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit /* Or whichever DtdProcessing option works for your scenario */ };
        return global::System.Xml.XmlReader.Create(new global::System.IO.StreamReader(stream), xmlReaderSettings);
    }
    catch(global::System.Xml.XmlException e)
    {
        throw new global::System.Xml.XmlException("Failed to create an XmlReader from the stream. Check if the resource exists.", e);
    }
}

@gathogojr
Copy link
Contributor

@zehavibarak OData Connected Service does help greatly in generating the proxy classes. However, if generating your own POCOs, you could opt to subclass the DataServiceContext by yourself and implement logic for fetching the service metadata and initializing the Edm model as follows:

internal class ExtendedDataServiceContext : DataServiceContext
{
	public ExtendedDataServiceContext(Uri serviceUri) : base(serviceUri)
	{
		Format.LoadServiceModel = LoadServiceModel;
		Format.UseJson();
	}

	private IEdmModel LoadServiceModel()
	{
		IEdmModel serviceModel;

                var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit /* Or whichever DtdProcessing option works for your scenario */ };
		using (var reader = XmlReader.Create(
                    /* TextReader for reading service metadata from file or network location */,
                    xmlReaderSettings))
		{
			if (!CsdlReader.TryParse(reader, out serviceModel, out IEnumerable<EdmError> errors))
			{
				throw new Exception(errors.Select(d => d.ErrorMessage).Aggregate((d, e) => string.Concat(d, "\r\n", e)));
			}
		}

		return serviceModel;
	}
}

@marabooy
Copy link
Member

marabooy commented Sep 3, 2024

@zehavibarak were you using the OData Connected service when you got this error?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants