diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 63d28d59896..1d14bce0677 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -101,6 +101,7 @@ The PR that reveals the implementation of the `Object type is not supported. - Resolving of external URIs was prohibited. + Resolving of external URIs was prohibited. Attempted access to: {0} Relative URIs are not supported. diff --git a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj index e9b3d71a468..405e6375a9f 100644 --- a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj +++ b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj @@ -127,13 +127,11 @@ - - + - @@ -748,6 +746,7 @@ + diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlNullResolver.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlNullResolver.cs deleted file mode 100644 index cae8ad85496..00000000000 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlNullResolver.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Net; - -namespace System.Xml -{ - internal sealed class XmlNullResolver : XmlResolver - { - public static readonly XmlNullResolver Singleton = new XmlNullResolver(); - - // Private constructor ensures existing only one instance of XmlNullResolver - private XmlNullResolver() { } - - public override object GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) - { - throw new XmlException(SR.Xml_NullResolver, string.Empty); - } - - public override ICredentials Credentials - { - set { /* Do nothing */ } - } - } -} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.ThrowingResolver.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.ThrowingResolver.cs new file mode 100644 index 00000000000..674ddb630e0 --- /dev/null +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.ThrowingResolver.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net; +using System.Threading.Tasks; + +namespace System.Xml +{ + public abstract partial class XmlResolver + { + /// + /// Gets an XML resolver which forbids entity resolution. + /// + /// An XML resolver which forbids entity resolution. + /// + /// Calling or on the + /// instance returned by this property is forbidden + /// and will result in being thrown. + /// + /// Use when external entity resolution must be + /// prohibited, even when DTD processing is otherwise enabled. + /// + public static XmlResolver ThrowingResolver => XmlThrowingResolver.s_singleton; + + // An XmlResolver that forbids all external entity resolution. + private sealed class XmlThrowingResolver : XmlResolver + { + internal static readonly XmlThrowingResolver s_singleton = new(); + + // Private constructor ensures existing only one instance of XmlThrowingResolver + private XmlThrowingResolver() { } + + public override ICredentials Credentials + { + set { /* Do nothing */ } + } + + public override object GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + throw new XmlException(SR.Format(SR.Xml_NullResolver, absoluteUri)); + } + + public override Task GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + throw new XmlException(SR.Format(SR.Xml_NullResolver, absoluteUri)); + } + } + } +} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.cs index 87d23a5341c..b5df8713be8 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlResolver.cs @@ -28,7 +28,12 @@ namespace System.Xml string? role, Type? ofObjectToReturn); - + public virtual Task GetEntityAsync(Uri absoluteUri, + string? role, + Type? ofObjectToReturn) + { + throw new NotImplementedException(); + } /// /// [To be supplied.] diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlResolverAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlResolverAsync.cs deleted file mode 100644 index 21504ff5e06..00000000000 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlResolverAsync.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Threading.Tasks; - -namespace System.Xml -{ - public abstract partial class XmlResolver - { - public virtual Task GetEntityAsync(Uri absoluteUri, - string? role, - Type? ofObjectToReturn) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolver.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolver.cs index aae411766ba..d5a8ca7761b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolver.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolver.cs @@ -3,32 +3,31 @@ using System.Net; using System.Security; -using System.Runtime.Versioning; +using System.Threading.Tasks; namespace System.Xml { - public partial class XmlSecureResolver : XmlResolver + [Obsolete(Obsoletions.XmlSecureResolverMessage, DiagnosticId = Obsoletions.XmlSecureResolverDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + public class XmlSecureResolver : XmlResolver { - private readonly XmlResolver _resolver; - public XmlSecureResolver(XmlResolver resolver, string? securityUrl) { - _resolver = resolver; + // no-op } public override ICredentials Credentials { - set { _resolver.Credentials = value; } + set { /* no-op */ } } - public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) - { - return _resolver.GetEntity(absoluteUri, role, ofObjectToReturn); - } + // Forward to ThrowingResolver to get its exception message + public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) => XmlResolver.ThrowingResolver.GetEntity(absoluteUri, role, ofObjectToReturn); - public override Uri ResolveUri(Uri? baseUri, string? relativeUri) - { - return _resolver.ResolveUri(baseUri, relativeUri); - } + // Forward to ThrowingResolver to get its exception message + public override Task GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) => XmlResolver.ThrowingResolver.GetEntityAsync(absoluteUri, role, ofObjectToReturn); + + // An earlier implementation of this type overrode this method, so we'll continue to do so + // to preserve binary compatibility. + public override Uri ResolveUri(Uri? baseUri, string? relativeUri) => base.ResolveUri(baseUri, relativeUri); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolverAsync.cs b/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolverAsync.cs deleted file mode 100644 index 59ffe4bcb36..00000000000 --- a/src/libraries/System.Private.Xml/src/System/Xml/XmlSecureResolverAsync.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Threading.Tasks; - -namespace System.Xml -{ - public partial class XmlSecureResolver : XmlResolver - { - public override Task GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) - { - return _resolver.GetEntityAsync(absoluteUri, role, ofObjectToReturn); - } - } -} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlILCommand.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlILCommand.cs index 53ffbdd9fb8..5d646eb6c6f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlILCommand.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlILCommand.cs @@ -83,7 +83,7 @@ namespace System.Xml.Xsl Debug.Assert(results != null); // Ensure that dataSources is always non-null - dataSources ??= XmlNullResolver.Singleton; + dataSources ??= XmlResolver.ThrowingResolver; _delExec(new XmlQueryRuntime(_staticData, defaultDocument, dataSources, argumentList, results)); } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs index 8b637b57b77..d5f44fe8234 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/Compiler.cs @@ -70,12 +70,12 @@ namespace System.Xml.Xsl.Xslt Scripts = new Scripts(this); } - public CompilerErrorCollection Compile(object stylesheet, XmlResolver? xmlResolver, out QilExpression qil) + public CompilerErrorCollection Compile(object stylesheet, XmlResolver? xmlResolver, XmlResolver? origResolver, out QilExpression qil) { Debug.Assert(stylesheet != null); Debug.Assert(Root == null, "Compiler cannot be reused"); - new XsltLoader().Load(this, stylesheet, xmlResolver); + new XsltLoader().Load(this, stylesheet, xmlResolver, origResolver); qil = QilGenerator.CompileStylesheet(this); SortErrors(); return CompilerErrorColl; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs index a77d24a3c1d..a0b2297a9bc 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/XsltLoader.cs @@ -38,11 +38,11 @@ namespace System.Xml.Xsl.Xslt public static int V2Opt = 4; public static int V2Req = 8; - public void Load(Compiler compiler, object stylesheet, XmlResolver? xmlResolver) + public void Load(Compiler compiler, object stylesheet, XmlResolver? xmlResolver, XmlResolver? origResolver) { Debug.Assert(compiler != null); _compiler = compiler; - _xmlResolver = xmlResolver ?? XmlNullResolver.Singleton; + _xmlResolver = xmlResolver ?? XmlResolver.ThrowingResolver; XmlReader? reader = stylesheet as XmlReader; if (reader != null) @@ -57,10 +57,21 @@ namespace System.Xml.Xsl.Xslt string? uri = stylesheet as string; if (uri != null) { - // If xmlResolver == null, then the original uri will be resolved using XmlUrlResolver - XmlResolver origResolver = xmlResolver!; - if (xmlResolver == null || xmlResolver == XmlNullResolver.Singleton) - origResolver = new XmlUrlResolver(); + // If the stylesheet has been provided as a string (URI, really), then we'll bounce + // through an XmlResolver to look up its contents. There's a complication here since + // the default resolver provided by our caller is likely a throwing resolver, and + // a throwing resolver would fail even when attempting to read this URL. We need + // to at minimum allow this URL to be read, because the user after all did explicitly + // ask us to do so. + // + // In this case, we'll rely on the 'origResolver' argument, which is the XmlResolver + // which was provided *to our caller* before any default substitution took place. + // If an explicit resolver was specified, we'll honor it. Otherwise we'll substitute + // an XmlUrlResolver for this one read operation. The stored resolver (which is used + // for reads beyond the initial stylesheet read) will use a throwing resolver as its + // default, as shown at the very top of this method. + + origResolver ??= new XmlUrlResolver(); Uri resolvedUri = origResolver.ResolveUri(null, uri); if (resolvedUri == null) { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs index b467573b7e1..32af222ca8b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XsltOld/Processor.cs @@ -345,7 +345,7 @@ namespace System.Xml.Xsl.XsltOld _builder = null; _actionStack = new HWStack(StackIncrement); _output = _rootAction.Output; - _resolver = resolver ?? XmlNullResolver.Singleton; + _resolver = resolver ?? XmlResolver.ThrowingResolver; _args = args ?? new XsltArgumentList(); _debugger = debugger; if (_debugger != null) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs index 7254705d6ee..4a734c289cb 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs @@ -82,7 +82,7 @@ namespace System.Xml.Xsl public void Load(XmlReader stylesheet) { Reset(); - LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver()); + LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver(), originalStylesheetResolver: null); } // SxS: This method does not take any resource name and does not expose any resources to the caller. @@ -90,7 +90,7 @@ namespace System.Xml.Xsl public void Load(XmlReader stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver) { Reset(); - LoadInternal(stylesheet, settings, stylesheetResolver); + LoadInternal(stylesheet, settings, stylesheetResolver, stylesheetResolver); } // SxS: This method does not take any resource name and does not expose any resources to the caller. @@ -98,7 +98,7 @@ namespace System.Xml.Xsl public void Load(IXPathNavigable stylesheet) { Reset(); - LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver()); + LoadInternal(stylesheet, XsltSettings.Default, CreateDefaultResolver(), originalStylesheetResolver: null); } // SxS: This method does not take any resource name and does not expose any resources to the caller. @@ -106,29 +106,32 @@ namespace System.Xml.Xsl public void Load(IXPathNavigable stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver) { Reset(); - LoadInternal(stylesheet, settings, stylesheetResolver); + LoadInternal(stylesheet, settings, stylesheetResolver, stylesheetResolver); } public void Load(string stylesheetUri) { Reset(); ArgumentNullException.ThrowIfNull(stylesheetUri); - LoadInternal(stylesheetUri, XsltSettings.Default, CreateDefaultResolver()); + LoadInternal(stylesheetUri, XsltSettings.Default, CreateDefaultResolver(), originalStylesheetResolver: null); } public void Load(string stylesheetUri, XsltSettings? settings, XmlResolver? stylesheetResolver) { Reset(); ArgumentNullException.ThrowIfNull(stylesheetUri); - LoadInternal(stylesheetUri, settings, stylesheetResolver); + LoadInternal(stylesheetUri, settings, stylesheetResolver, stylesheetResolver); } - private void LoadInternal(object stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver) + // The 'originalStylesheetResolver' argument should be the original XmlResolver + // that was passed to the caller (or null), *before* any default substitutions + // were made by the caller. + private void LoadInternal(object stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver, XmlResolver? originalStylesheetResolver) { ArgumentNullException.ThrowIfNull(stylesheet); settings ??= XsltSettings.Default; - CompileXsltToQil(stylesheet, settings, stylesheetResolver); + CompileXsltToQil(stylesheet, settings, stylesheetResolver, originalStylesheetResolver); CompilerError? error = GetFirstError(); if (error != null) { @@ -142,9 +145,9 @@ namespace System.Xml.Xsl [MemberNotNull(nameof(_compilerErrorColl))] [MemberNotNull(nameof(_qil))] - private void CompileXsltToQil(object stylesheet, XsltSettings settings, XmlResolver? stylesheetResolver) + private void CompileXsltToQil(object stylesheet, XsltSettings settings, XmlResolver? stylesheetResolver, XmlResolver? originalStylesheetResolver) { - _compilerErrorColl = new Compiler(settings, _enableDebug, null).Compile(stylesheet, stylesheetResolver, out _qil); + _compilerErrorColl = new Compiler(settings, _enableDebug, null).Compile(stylesheet, stylesheetResolver, originalStylesheetResolver, out _qil); } /// @@ -405,7 +408,7 @@ namespace System.Xml.Xsl return new XmlUrlResolver(); } - return XmlNullResolver.Singleton; + return XmlResolver.ThrowingResolver; } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs index fbc9448619f..15826ec1d9c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslTransform.cs @@ -246,7 +246,7 @@ namespace System.Xml.Xsl Compiler compiler = new Compiler(); NavigatorInput input = new NavigatorInput(stylesheet); - compiler.Compile(input, resolver ?? XmlNullResolver.Singleton); + compiler.Compile(input, resolver ?? XmlResolver.ThrowingResolver); Debug.Assert(compiler.CompiledStylesheet != null); Debug.Assert(compiler.QueryStore != null); @@ -264,7 +264,7 @@ namespace System.Xml.Xsl } else { - return XmlNullResolver.Singleton; + return XmlResolver.ThrowingResolver; } } } diff --git a/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj b/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj index 7c7c909e2fe..7e365510221 100644 --- a/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/Misc/System.Xml.Misc.Tests.csproj @@ -4,6 +4,8 @@ $(NetCoreAppCurrent) + + diff --git a/src/libraries/System.Private.Xml/tests/Misc/XmlSecureResolverTests.cs b/src/libraries/System.Private.Xml/tests/Misc/XmlSecureResolverTests.cs new file mode 100644 index 00000000000..64dbd4b8dec --- /dev/null +++ b/src/libraries/System.Private.Xml/tests/Misc/XmlSecureResolverTests.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Net; +using System.Reflection; +using System.Threading.Tasks; +using Xunit; + +#pragma warning disable SYSLIB0047 // XmlSecureResolver is obsolete + +namespace System.Xml.Tests +{ + public class XmlSecureResolverTests + { + [Fact] + public void GetEntity_ThrowsXmlException() + { + PoisonedXmlResolver innerResolver = new PoisonedXmlResolver(); + XmlSecureResolver outerResolver = new XmlSecureResolver(innerResolver, "some-url"); + Uri absoluteUri = new Uri("https://dot.net/"); + Type typeToReturn = typeof(Stream); + + Assert.Throws(() => outerResolver.GetEntity(absoluteUri, "role", typeToReturn)); + Assert.False(innerResolver.WasAnyApiInvoked); + } + + [Fact] + public void GetEntityAsync_ThrowsXmlException() + { + PoisonedXmlResolver innerResolver = new PoisonedXmlResolver(); + XmlSecureResolver outerResolver = new XmlSecureResolver(innerResolver, "some-url"); + Uri absoluteUri = new Uri("https://dot.net/"); + Type typeToReturn = typeof(Stream); + + Assert.Throws(() => (object)outerResolver.GetEntityAsync(absoluteUri, "role", typeToReturn)); + Assert.False(innerResolver.WasAnyApiInvoked); + } + + [Fact] + public void Instance_HasNoState() + { + // This is a safety check to ensure we're not keeping the inner resolver in an instance field, + // since we don't want to risk invoking it. + + FieldInfo[] allDeclaredInstanceFields = typeof(XmlSecureResolver).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + Assert.Empty(allDeclaredInstanceFields); + } + + private sealed class PoisonedXmlResolver : XmlResolver + { + public bool WasAnyApiInvoked { get; private set; } + + public override ICredentials Credentials + { + set + { + WasAnyApiInvoked = true; + throw new NotImplementedException(); + } + } + + public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + WasAnyApiInvoked = true; + throw new NotImplementedException(); + } + + public override Task GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + WasAnyApiInvoked = true; + throw new NotImplementedException(); + } + + public override Uri ResolveUri(Uri? baseUri, string? relativeUri) + { + WasAnyApiInvoked = true; + throw new NotImplementedException(); + } + + public override bool SupportsType(Uri absoluteUri, Type? type) + { + WasAnyApiInvoked = true; + throw new NotImplementedException(); + } + } + } +} diff --git a/src/libraries/System.Private.Xml/tests/Misc/XmlThrowingResolverTests.cs b/src/libraries/System.Private.Xml/tests/Misc/XmlThrowingResolverTests.cs new file mode 100644 index 00000000000..9943057677a --- /dev/null +++ b/src/libraries/System.Private.Xml/tests/Misc/XmlThrowingResolverTests.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using Xunit; + +namespace System.Xml.Tests +{ + public class XmlThrowingResolverTests + { + [Fact] + public void PropertyAccessor_ReturnsSingleton() + { + XmlResolver resolver1 = XmlResolver.ThrowingResolver; + Assert.NotNull(resolver1); + + XmlResolver resolver2 = XmlResolver.ThrowingResolver; + Assert.Same(resolver1, resolver2); + Assert.Equal(resolver1, resolver2); // default comparer should also say they're equal + } + + [Fact] + public void GetEntity_ThrowsXmlException() + { + XmlResolver resolver = XmlResolver.ThrowingResolver; + Uri absoluteUri = new Uri("https://dot.net/"); + Type typeToReturn = typeof(Stream); + + Assert.Throws(() => resolver.GetEntity(absoluteUri, "role", typeToReturn)); + } + + [Fact] + public void GetEntityAsync_ThrowsXmlException() + { + XmlResolver resolver = XmlResolver.ThrowingResolver; + Uri absoluteUri = new Uri("https://dot.net/"); + Type typeToReturn = typeof(Stream); + + Assert.Throws(() => (object)resolver.GetEntityAsync(absoluteUri, "role", typeToReturn)); + } + } +} diff --git a/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs b/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs index 1515ad5c5fc..55d32e737b5 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs +++ b/src/libraries/System.Private.Xml/tests/XmlSchema/XmlSchemaValidatorApi/CXmlTestResolver.cs @@ -86,12 +86,6 @@ namespace System.Xml.Tests _resolver = new XmlUrlResolver(); } - public CXmlTestResolver(string securityUri) - : base() - { - _resolver = new XmlSecureResolver(new XmlUrlResolver(), securityUri); - } - // ----------------- // Events // ----------------- diff --git a/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApi/Exceptions.xml b/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApi/Exceptions.xml index 442eb4ef712..64539830495 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApi/Exceptions.xml +++ b/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApi/Exceptions.xml @@ -98,6 +98,6 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Exceptions.xml b/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Exceptions.xml index ffc3a7b8a7c..7978a96ab9a 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Exceptions.xml +++ b/src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/XsltApiV2/Exceptions.xml @@ -101,6 +101,6 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs index c62332a5cc7..89b19b00a0f 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs @@ -5,6 +5,7 @@ using Xunit; using Xunit.Abstractions; using System; using System.Collections; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; @@ -1486,6 +1487,35 @@ namespace System.Xml.Tests _output.WriteLine("Passing null stylesheet parameter should have thrown ArgumentNullException"); Assert.True(false); } + + //[Variation("Call Load with custom resolver; custom resolver should be honored.")] + [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)] + [Theory] + public void LoadUrlResolver4(XslInputType xslInputType, ReaderType readerType) + { + var auditingResolver = new XmlAuditingUrlResolver(); + LoadXSL_Resolver(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl"), xslInputType, readerType, auditingResolver); + + HashSet expected = new() + { + new Uri(Path.Combine(Environment.CurrentDirectory, FullFilePath(Path.Combine("XmlResolver", "XmlResolverTestMain.xsl")))), + new Uri(Path.Combine(Environment.CurrentDirectory, FullFilePath(Path.Combine("XmlResolver", "XmlResolverInclude.xsl")))), + new Uri(Path.Combine(Environment.CurrentDirectory, FullFilePath(Path.Combine("XmlResolver", "XmlResolverImport.xsl")))), + }; + + Assert.Equal(expected, auditingResolver.FetchedUris); + } + + private sealed class XmlAuditingUrlResolver : XmlUrlResolver + { + internal readonly HashSet FetchedUris = new(); + + public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + FetchedUris.Add(absoluteUri); + return base.GetEntity(absoluteUri, role, ofObjectToReturn); + } + } } /***********************************************************/ diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs index 1ec189b53e9..5220c7d3693 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslTransformApi/CXslTransform.cs @@ -1019,7 +1019,8 @@ namespace System.Xml.Tests } catch (System.Xml.Xsl.XsltCompileException e) { - CheckExpectedError(e.InnerException, "System.Xml", "Xml_NullResolver", new string[] { "" }); + var absoluteUri = new Uri(Path.Combine(Environment.CurrentDirectory, FullFilePath("XmlResolver_Include.xsl"))).AbsoluteUri; + CheckExpectedError(e.InnerException, "System.Xml", "Xml_NullResolver", new string[] { absoluteUri }); return; } _output.WriteLine("Exception not thrown for null resolver"); @@ -1104,7 +1105,9 @@ namespace System.Xml.Tests Assert.False(isEnabled); var e = Assert.Throws(() => LoadXSL("XmlResolver_Main.xsl", inputType, readerType)); var xmlException = Assert.IsType(e.InnerException); - CheckExpectedError(xmlException, "System.Xml", "Xml_NullResolver", Array.Empty()); + + var absoluteUri = new Uri(Path.Combine(Environment.CurrentDirectory, FullFilePath("XmlResolver_Include.xsl"))).AbsoluteUri; + CheckExpectedError(xmlException, "System.Xml", "Xml_NullResolver", new string[] { absoluteUri }); } //[Variation("Load with resolver with credentials, then load XSL that does not need cred.")] diff --git a/src/libraries/System.Security.Cryptography.Xml/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Xml/src/Resources/Strings.resx index 78697d97f96..88441504b6f 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Xml/src/Resources/Strings.resx @@ -393,4 +393,7 @@ Root element must be {0} element in namespace {1} - + + External entity resolution is not supported. + + \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj index e0b9361891a..20a3d77a464 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) true @@ -126,6 +126,7 @@ System.Security.Cryptography.Xml.XmlLicenseTransform + diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs index 13295058f5e..05c7625170e 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs @@ -359,7 +359,7 @@ namespace System.Security.Cryptography.Xml { case ReferenceTargetType.Stream: // This is the easiest case. We already have a stream, so just pump it through the TransformChain - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); hashInputStream = TransformChain.TransformToOctetStream((Stream)_refTarget, resolver, baseUri); break; case ReferenceTargetType.UriReference: @@ -369,7 +369,7 @@ namespace System.Security.Cryptography.Xml if (_uri == null) { // We need to create a DocumentNavigator out of the XmlElement - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); // In the case of a Uri-less reference, we will simply pass null to the transform chain. // The first transform in the chain is expected to know how to retrieve the data to hash. hashInputStream = TransformChain.TransformToOctetStream((Stream)null, resolver, baseUri); @@ -382,7 +382,7 @@ namespace System.Security.Cryptography.Xml throw new CryptographicException(SR.Format(SR.Cryptography_Xml_SelfReferenceRequiresContext, _uri)); // Normalize the containing document - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); XmlDocument docWithNoComments = Utils.DiscardComments(Utils.PreProcessDocumentInput(document, resolver, baseUri)); hashInputStream = TransformChain.TransformToOctetStream(docWithNoComments, resolver, baseUri); } @@ -398,7 +398,7 @@ namespace System.Security.Cryptography.Xml throw new CryptographicException(SR.Format(SR.Cryptography_Xml_SelfReferenceRequiresContext, _uri)); // We should not discard comments here!!! - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessDocumentInput(document, resolver, baseUri), resolver, baseUri); break; } @@ -434,7 +434,7 @@ namespace System.Security.Cryptography.Xml // Add the propagated attributes Utils.AddNamespaces(normDocument.DocumentElement, _namespaces); - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); if (discardComments) { // We should discard comments before going into the transform chain @@ -454,7 +454,7 @@ namespace System.Security.Cryptography.Xml break; case ReferenceTargetType.XmlElement: // We need to create a DocumentNavigator out of the XmlElement - resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver()); hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessElementInput((XmlElement)_refTarget, resolver, baseUri), resolver, baseUri); break; default: diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs index a717789c742..5d722d0f180 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs @@ -775,7 +775,7 @@ namespace System.Security.Cryptography.Xml if (isKeyedHashAlgorithm || !_bCacheValid || !SignedInfo.CacheValid) { string baseUri = _containingDocument?.BaseURI; - XmlResolver resolver = (_bResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); + XmlResolver resolver = (_bResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); XmlDocument doc = Utils.PreProcessElementInput(SignedInfo.GetXml(), resolver, baseUri); // Add non default namespaces in scope diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs index fe3fceb39ba..b31bf6a7003 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs @@ -142,7 +142,7 @@ namespace System.Security.Cryptography.Xml { XmlDocument document = new XmlDocument(); document.PreserveWhitespace = true; - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI); document.Load(xmlReader); _containingDocument = document; diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs index b27276b370c..d70778e8fcf 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs @@ -47,7 +47,7 @@ namespace System.Security.Cryptography.Xml public override void LoadInput(object obj) { - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); if (obj is Stream) { _cXml = new CanonicalXml((Stream)obj, _includeComments, resolver, BaseURI); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs index 996a9fb5997..3aa5b2b5cbb 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs @@ -79,7 +79,7 @@ namespace System.Security.Cryptography.Xml { XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI); doc.Load(xmlReader); _containingDocument = doc; diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs index dba65b391ce..e0007c207fc 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs @@ -74,7 +74,7 @@ namespace System.Security.Cryptography.Xml public override void LoadInput(object obj) { - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); if (obj is Stream) { _excCanonicalXml = new ExcCanonicalXml((Stream)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver, BaseURI); diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs index 1e8d6e384dd..bd5675c3640 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs @@ -133,7 +133,7 @@ namespace System.Security.Cryptography.Xml private void LoadStreamInput(Stream stream) { - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); XmlReader valReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI); _document = new XmlDocument(); _document.PreserveWhitespace = true; @@ -143,7 +143,7 @@ namespace System.Security.Cryptography.Xml private void LoadXmlNodeListInput(XmlNodeList nodeList) { // Use C14N to get a document - XmlResolver resolver = (ResolverSet ? _xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), BaseURI)); + XmlResolver resolver = (ResolverSet ? _xmlResolver : XmlResolverHelper.GetThrowingResolver()); CanonicalXml c14n = new CanonicalXml((XmlNodeList)nodeList, resolver, true); using (MemoryStream ms = new MemoryStream(c14n.GetBytes())) { diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs new file mode 100644 index 00000000000..3070ffa8e1d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlResolverHelper.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net; +using System.Threading.Tasks; +using System.Xml; + +namespace System.Security.Cryptography.Xml +{ + internal static class XmlResolverHelper + { + internal static XmlResolver GetThrowingResolver() + { +#if NET7_0_OR_GREATER + return XmlResolver.ThrowingResolver; +#else + return XmlThrowingResolver.s_singleton; +#endif + } + +#if !NET7_0_OR_GREATER + // An XmlResolver that forbids all external entity resolution. + // (Copied from XmlResolver.ThrowingResolver.cs.) + private sealed class XmlThrowingResolver : XmlResolver + { + internal static readonly XmlThrowingResolver s_singleton = new(); + + // Private constructor ensures existing only one instance of XmlThrowingResolver + private XmlThrowingResolver() { } + + public override ICredentials Credentials + { + set { /* Do nothing */ } + } + + public override object GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + throw new XmlException(SR.Cryptography_Xml_EntityResolutionNotSupported); + } + + public override Task GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) + { + throw new XmlException(SR.Cryptography_Xml_EntityResolutionNotSupported); + } + } +#endif + } +} diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs index ac5d3560a32..54f00d1154c 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs +++ b/src/libraries/System.Security.Cryptography.Xml/tests/SignedXmlTest.cs @@ -11,8 +11,11 @@ using System.Globalization; using System.IO; +using System.Net; using System.Security.Cryptography.X509Certificates; using System.Text; +using System.Threading; +using System.Threading.Tasks; using System.Xml; using System.Xml.XPath; using Test.Cryptography; @@ -1587,6 +1590,127 @@ namespace System.Security.Cryptography.Xml.Tests Assert.Throws(() => sign.CheckSignature(new HMACSHA1("no clue"u8.ToArray()))); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void VerifyXmlResolver(bool provideResolver) + { + HttpListener listener; + int port = 9000; + + while (true) + { + listener = new HttpListener(); + listener.Prefixes.Add($"http://127.0.0.1:{port}/"); + listener.IgnoreWriteExceptions = true; + + try + { + listener.Start(); + break; + } + catch + { + } + + port++; + + if (port > 10000) + { + throw new InvalidOperationException("Could not find an open port"); + } + } + + string xml = $@"]> +Example doc to be signed.&xxe; + + + + + + + + + CLUSJx4H4EwydAT/CtNWYu/l6R8uZe0tO2rlM/o0iM4= + + + o0IAVyovNUYKs5CCIRpZVy6noLpdJBp8LwWrqzzhKPg= + +"; + + bool listenerContacted = false; + CancellationTokenSource tokenSource = new CancellationTokenSource(); + Task listenerTask = ProcessRequests(listener, req => listenerContacted = true, tokenSource.Token); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + + SignedXml signedXml = new SignedXml(doc); + signedXml.LoadXml((XmlElement)doc.GetElementsByTagName("Signature")[0]); + + try + { + using (HMAC key = new HMACSHA256(Encoding.UTF8.GetBytes("sample"))) + { + if (provideResolver) + { + signedXml.Resolver = new XmlUrlResolver(); + Assert.True(signedXml.CheckSignature(key), "signedXml.CheckSignature(key)"); + Assert.True(listenerContacted, "listenerContacted"); + } + else + { + XmlException ex = Assert.Throws(() => signedXml.CheckSignature(key)); + Assert.False(listenerContacted, "listenerContacted"); + } + } + } + finally + { + tokenSource.Cancel(); + + try + { + listener.Stop(); + } + catch + { + } + + ((IDisposable)listener).Dispose(); + } + + static async Task ProcessRequests( + HttpListener listener, + Action requestReceived, + CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + HttpListenerContext ctx; + + try + { + ctx = await listener.GetContextAsync(); + } + catch + { + break; + } + + HttpListenerRequest req = ctx.Request; + requestReceived(req); + + using (HttpListenerResponse resp = ctx.Response) + { + resp.ContentType = "text/plain"; + resp.ContentEncoding = Encoding.UTF8; + resp.ContentLength64 = 0; + } + } + } + } + [Fact] public void CoreFxSignedXmlUsesSha256ByDefault() { diff --git a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs index 676247bba16..0f7257bcebc 100644 --- a/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs +++ b/src/libraries/System.Xml.ReaderWriter/ref/System.Xml.ReaderWriter.cs @@ -948,11 +948,13 @@ namespace System.Xml { protected XmlResolver() { } public virtual System.Net.ICredentials Credentials { set { } } + public static System.Xml.XmlResolver ThrowingResolver { get { throw null; } } public abstract object? GetEntity(System.Uri absoluteUri, string? role, System.Type? ofObjectToReturn); public virtual System.Threading.Tasks.Task GetEntityAsync(System.Uri absoluteUri, string? role, System.Type? ofObjectToReturn) { throw null; } public virtual System.Uri ResolveUri(System.Uri? baseUri, string? relativeUri) { throw null; } public virtual bool SupportsType(System.Uri absoluteUri, System.Type? type) { throw null; } } + [System.ObsoleteAttribute("XmlSecureResolver is obsolete. Use XmlResolver.ThrowingResolver instead when attempting to forbid XML external entity resolution.", DiagnosticId = "SYSLIB0047", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] public partial class XmlSecureResolver : System.Xml.XmlResolver { public XmlSecureResolver(System.Xml.XmlResolver resolver, string? securityUrl) { }