1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 01:50:53 +09:00

Obsolete XmlSecureResolver (#73676)

- Add XmlResolver.ThrowingResolver
- Migrate all call sites to the new API
- Improve error messages on failure

Resolves CVE-2022-34716.
This commit is contained in:
Levi Broderick 2022-08-12 12:55:05 -07:00 committed by GitHub
parent f44da5225f
commit d2afae4fb0
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 474 additions and 124 deletions

View file

@ -101,6 +101,7 @@ The PR that reveals the implementation of the `<IncludeInternalObsoleteAttribute
| __`SYSLIB0044`__ | AssemblyName.CodeBase and AssemblyName.EscapedCodeBase are obsolete. Using them for loading an assembly is not supported. | | __`SYSLIB0044`__ | AssemblyName.CodeBase and AssemblyName.EscapedCodeBase are obsolete. Using them for loading an assembly is not supported. |
| __`SYSLIB0045`__ | Cryptographic factory methods accepting an algorithm name are obsolete. Use the parameterless Create factory method on the algorithm type instead. | | __`SYSLIB0045`__ | Cryptographic factory methods accepting an algorithm name are obsolete. Use the parameterless Create factory method on the algorithm type instead. |
| __`SYSLIB0046`__ | ControlledExecution.Run method may corrupt the process and should not be used in production code. | | __`SYSLIB0046`__ | ControlledExecution.Run method may corrupt the process and should not be used in production code. |
| __`SYSLIB0047`__ | XmlSecureResolver is obsolete. Use XmlResolver.ThrowingResolver instead when attempting to forbid XML external entity resolution. |
## Analyzer Warnings ## Analyzer Warnings

View file

@ -150,5 +150,8 @@ namespace System
internal const string ControlledExecutionRunMessage = "ControlledExecution.Run method may corrupt the process and should not be used in production code."; internal const string ControlledExecutionRunMessage = "ControlledExecution.Run method may corrupt the process and should not be used in production code.";
internal const string ControlledExecutionRunDiagId = "SYSLIB0046"; internal const string ControlledExecutionRunDiagId = "SYSLIB0046";
internal const string XmlSecureResolverMessage = "XmlSecureResolver is obsolete. Use XmlResolver.ThrowingResolver instead when attempting to forbid XML external entity resolution.";
internal const string XmlSecureResolverDiagId = "SYSLIB0047";
} }
} }

View file

@ -514,7 +514,7 @@
<value>Object type is not supported.</value> <value>Object type is not supported.</value>
</data> </data>
<data name="Xml_NullResolver" xml:space="preserve"> <data name="Xml_NullResolver" xml:space="preserve">
<value>Resolving of external URIs was prohibited.</value> <value>Resolving of external URIs was prohibited. Attempted access to: {0}</value>
</data> </data>
<data name="Xml_RelativeUriNotSupported" xml:space="preserve"> <data name="Xml_RelativeUriNotSupported" xml:space="preserve">
<value>Relative URIs are not supported.</value> <value>Relative URIs are not supported.</value>

View file

@ -127,13 +127,11 @@
<Compile Include="System\Xml\XmlNameTable.cs" /> <Compile Include="System\Xml\XmlNameTable.cs" />
<Compile Include="System\Xml\XmlNodeOrder.cs" /> <Compile Include="System\Xml\XmlNodeOrder.cs" />
<Compile Include="System\Xml\XmlNodeType.cs" /> <Compile Include="System\Xml\XmlNodeType.cs" />
<Compile Include="System\Xml\XmlNullResolver.cs" />
<Compile Include="System\Xml\XmlQualifiedName.cs" /> <Compile Include="System\Xml\XmlQualifiedName.cs" />
<Compile Include="System\Xml\XmlReservedNs.cs" /> <Compile Include="System\Xml\XmlReservedNs.cs" />
<Compile Include="System\Xml\XmlResolver.cs" /> <Compile Include="System\Xml\XmlResolver.cs" />
<Compile Include="System\Xml\XmlResolverAsync.cs" /> <Compile Include="System\Xml\XmlResolver.ThrowingResolver.cs" />
<Compile Include="System\Xml\XmlSecureResolver.cs" /> <Compile Include="System\Xml\XmlSecureResolver.cs" />
<Compile Include="System\Xml\XmlSecureResolverAsync.cs" />
<Compile Include="System\Xml\XmlUrlResolver.cs" /> <Compile Include="System\Xml\XmlUrlResolver.cs" />
<Compile Include="System\Xml\XmlUrlResolverAsync.cs" /> <Compile Include="System\Xml\XmlUrlResolverAsync.cs" />
<Compile Include="System\Xml\Core\CharEntityEncoderFallback.cs" /> <Compile Include="System\Xml\Core\CharEntityEncoderFallback.cs" />
@ -748,6 +746,7 @@
<Compile Include="$(CommonPath)System\CSharpHelpers.cs" /> <Compile Include="$(CommonPath)System\CSharpHelpers.cs" />
<Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs" Link="Common\System\Text\ValueStringBuilder.cs" /> <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.cs" Link="Common\System\Text\ValueStringBuilder.cs" />
<Compile Include="$(CommonPath)System\Text\ValueStringBuilder.AppendSpanFormattable.cs" Link="Common\System\Text\ValueStringBuilder.AppendSpanFormattable.cs" /> <Compile Include="$(CommonPath)System\Text\ValueStringBuilder.AppendSpanFormattable.cs" Link="Common\System\Text\ValueStringBuilder.AppendSpanFormattable.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs" Link="Common\System\Obsoletions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'"> <ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">

View file

@ -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 */ }
}
}
}

View file

@ -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
{
/// <summary>
/// Gets an XML resolver which forbids entity resolution.
/// </summary>
/// <value>An XML resolver which forbids entity resolution.</value>
/// <remarks>
/// Calling <see cref="GetEntity"/> or <see cref="GetEntityAsync"/> on the
/// <see cref="XmlResolver"/> instance returned by this property is forbidden
/// and will result in <see cref="XmlException"/> being thrown.
///
/// Use <see cref="ThrowingResolver"/> when external entity resolution must be
/// prohibited, even when DTD processing is otherwise enabled.
/// </remarks>
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<object> GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
throw new XmlException(SR.Format(SR.Xml_NullResolver, absoluteUri));
}
}
}
}

View file

@ -28,7 +28,12 @@ namespace System.Xml
string? role, string? role,
Type? ofObjectToReturn); Type? ofObjectToReturn);
public virtual Task<object> GetEntityAsync(Uri absoluteUri,
string? role,
Type? ofObjectToReturn)
{
throw new NotImplementedException();
}
/// <devdoc> /// <devdoc>
/// <para>[To be supplied.]</para> /// <para>[To be supplied.]</para>

View file

@ -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<object> GetEntityAsync(Uri absoluteUri,
string? role,
Type? ofObjectToReturn)
{
throw new NotImplementedException();
}
}
}

View file

@ -3,32 +3,31 @@
using System.Net; using System.Net;
using System.Security; using System.Security;
using System.Runtime.Versioning; using System.Threading.Tasks;
namespace System.Xml 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) public XmlSecureResolver(XmlResolver resolver, string? securityUrl)
{ {
_resolver = resolver; // no-op
} }
public override ICredentials Credentials public override ICredentials Credentials
{ {
set { _resolver.Credentials = value; } set { /* no-op */ }
} }
public override object? GetEntity(Uri absoluteUri, string? role, Type? 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);
return _resolver.GetEntity(absoluteUri, role, ofObjectToReturn);
}
public override Uri ResolveUri(Uri? baseUri, string? relativeUri) // Forward to ThrowingResolver to get its exception message
{ public override Task<object> GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn) => XmlResolver.ThrowingResolver.GetEntityAsync(absoluteUri, role, ofObjectToReturn);
return _resolver.ResolveUri(baseUri, relativeUri);
} // 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);
} }
} }

View file

@ -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<object> GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
return _resolver.GetEntityAsync(absoluteUri, role, ofObjectToReturn);
}
}
}

View file

@ -83,7 +83,7 @@ namespace System.Xml.Xsl
Debug.Assert(results != null); Debug.Assert(results != null);
// Ensure that dataSources is always non-null // Ensure that dataSources is always non-null
dataSources ??= XmlNullResolver.Singleton; dataSources ??= XmlResolver.ThrowingResolver;
_delExec(new XmlQueryRuntime(_staticData, defaultDocument, dataSources, argumentList, results)); _delExec(new XmlQueryRuntime(_staticData, defaultDocument, dataSources, argumentList, results));
} }

View file

@ -70,12 +70,12 @@ namespace System.Xml.Xsl.Xslt
Scripts = new Scripts(this); 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(stylesheet != null);
Debug.Assert(Root == null, "Compiler cannot be reused"); 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); qil = QilGenerator.CompileStylesheet(this);
SortErrors(); SortErrors();
return CompilerErrorColl; return CompilerErrorColl;

View file

@ -38,11 +38,11 @@ namespace System.Xml.Xsl.Xslt
public static int V2Opt = 4; public static int V2Opt = 4;
public static int V2Req = 8; 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); Debug.Assert(compiler != null);
_compiler = compiler; _compiler = compiler;
_xmlResolver = xmlResolver ?? XmlNullResolver.Singleton; _xmlResolver = xmlResolver ?? XmlResolver.ThrowingResolver;
XmlReader? reader = stylesheet as XmlReader; XmlReader? reader = stylesheet as XmlReader;
if (reader != null) if (reader != null)
@ -57,10 +57,21 @@ namespace System.Xml.Xsl.Xslt
string? uri = stylesheet as string; string? uri = stylesheet as string;
if (uri != null) if (uri != null)
{ {
// If xmlResolver == null, then the original uri will be resolved using XmlUrlResolver // If the stylesheet has been provided as a string (URI, really), then we'll bounce
XmlResolver origResolver = xmlResolver!; // through an XmlResolver to look up its contents. There's a complication here since
if (xmlResolver == null || xmlResolver == XmlNullResolver.Singleton) // the default resolver provided by our caller is likely a throwing resolver, and
origResolver = new XmlUrlResolver(); // 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); Uri resolvedUri = origResolver.ResolveUri(null, uri);
if (resolvedUri == null) if (resolvedUri == null)
{ {

View file

@ -345,7 +345,7 @@ namespace System.Xml.Xsl.XsltOld
_builder = null; _builder = null;
_actionStack = new HWStack(StackIncrement); _actionStack = new HWStack(StackIncrement);
_output = _rootAction.Output; _output = _rootAction.Output;
_resolver = resolver ?? XmlNullResolver.Singleton; _resolver = resolver ?? XmlResolver.ThrowingResolver;
_args = args ?? new XsltArgumentList(); _args = args ?? new XsltArgumentList();
_debugger = debugger; _debugger = debugger;
if (_debugger != null) if (_debugger != null)

View file

@ -82,7 +82,7 @@ namespace System.Xml.Xsl
public void Load(XmlReader stylesheet) public void Load(XmlReader stylesheet)
{ {
Reset(); 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. // 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) public void Load(XmlReader stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver)
{ {
Reset(); 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. // 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) public void Load(IXPathNavigable stylesheet)
{ {
Reset(); 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. // 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) public void Load(IXPathNavigable stylesheet, XsltSettings? settings, XmlResolver? stylesheetResolver)
{ {
Reset(); Reset();
LoadInternal(stylesheet, settings, stylesheetResolver); LoadInternal(stylesheet, settings, stylesheetResolver, stylesheetResolver);
} }
public void Load(string stylesheetUri) public void Load(string stylesheetUri)
{ {
Reset(); Reset();
ArgumentNullException.ThrowIfNull(stylesheetUri); ArgumentNullException.ThrowIfNull(stylesheetUri);
LoadInternal(stylesheetUri, XsltSettings.Default, CreateDefaultResolver()); LoadInternal(stylesheetUri, XsltSettings.Default, CreateDefaultResolver(), originalStylesheetResolver: null);
} }
public void Load(string stylesheetUri, XsltSettings? settings, XmlResolver? stylesheetResolver) public void Load(string stylesheetUri, XsltSettings? settings, XmlResolver? stylesheetResolver)
{ {
Reset(); Reset();
ArgumentNullException.ThrowIfNull(stylesheetUri); 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); ArgumentNullException.ThrowIfNull(stylesheet);
settings ??= XsltSettings.Default; settings ??= XsltSettings.Default;
CompileXsltToQil(stylesheet, settings, stylesheetResolver); CompileXsltToQil(stylesheet, settings, stylesheetResolver, originalStylesheetResolver);
CompilerError? error = GetFirstError(); CompilerError? error = GetFirstError();
if (error != null) if (error != null)
{ {
@ -142,9 +145,9 @@ namespace System.Xml.Xsl
[MemberNotNull(nameof(_compilerErrorColl))] [MemberNotNull(nameof(_compilerErrorColl))]
[MemberNotNull(nameof(_qil))] [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);
} }
/// <summary> /// <summary>
@ -405,7 +408,7 @@ namespace System.Xml.Xsl
return new XmlUrlResolver(); return new XmlUrlResolver();
} }
return XmlNullResolver.Singleton; return XmlResolver.ThrowingResolver;
} }
} }
} }

View file

@ -246,7 +246,7 @@ namespace System.Xml.Xsl
Compiler compiler = new Compiler(); Compiler compiler = new Compiler();
NavigatorInput input = new NavigatorInput(stylesheet); 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.CompiledStylesheet != null);
Debug.Assert(compiler.QueryStore != null); Debug.Assert(compiler.QueryStore != null);
@ -264,7 +264,7 @@ namespace System.Xml.Xsl
} }
else else
{ {
return XmlNullResolver.Singleton; return XmlResolver.ThrowingResolver;
} }
} }
} }

View file

@ -4,6 +4,8 @@
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework> <TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="XmlThrowingResolverTests.cs" />
<Compile Include="XmlSecureResolverTests.cs" />
<Compile Include="XmlUrlResolverTests.cs" /> <Compile Include="XmlUrlResolverTests.cs" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -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<XmlException>(() => 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<XmlException>(() => (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<object> 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();
}
}
}
}

View file

@ -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<XmlException>(() => 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<XmlException>(() => (object)resolver.GetEntityAsync(absoluteUri, "role", typeToReturn));
}
}
}

View file

@ -86,12 +86,6 @@ namespace System.Xml.Tests
_resolver = new XmlUrlResolver(); _resolver = new XmlUrlResolver();
} }
public CXmlTestResolver(string securityUri)
: base()
{
_resolver = new XmlSecureResolver(new XmlUrlResolver(), securityUri);
}
// ----------------- // -----------------
// Events // Events
// ----------------- // -----------------

View file

@ -98,6 +98,6 @@
<!-- XML Exceptions --> <!-- XML Exceptions -->
<exception res="Xml_BadStartNameChar" message="The '{0}' character, hexadecimal value {1}, cannot begin a name."/> <exception res="Xml_BadStartNameChar" message="The '{0}' character, hexadecimal value {1}, cannot begin a name."/>
<exception res="Xml_ResolveUrl" message="There was an error accessing {0}."/> <exception res="Xml_ResolveUrl" message="There was an error accessing {0}."/>
<exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. "/> <exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. Attempted access to: {0}"/>
</exceptions> </exceptions>

View file

@ -101,6 +101,6 @@
<!-- XML Exceptions --> <!-- XML Exceptions -->
<exception res="Xml_BadStartNameChar" message="The '{0}' character, hexadecimal value {1}, cannot begin a name."/> <exception res="Xml_BadStartNameChar" message="The '{0}' character, hexadecimal value {1}, cannot begin a name."/>
<exception res="Xml_ResolveUrl" message="There was an error accessing {0}."/> <exception res="Xml_ResolveUrl" message="There was an error accessing {0}."/>
<exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. "/> <exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. Attempted access to: {0}"/>
</exceptions> </exceptions>

View file

@ -5,6 +5,7 @@ using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -1486,6 +1487,35 @@ namespace System.Xml.Tests
_output.WriteLine("Passing null stylesheet parameter should have thrown ArgumentNullException"); _output.WriteLine("Passing null stylesheet parameter should have thrown ArgumentNullException");
Assert.True(false); 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<Uri> 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<Uri> FetchedUris = new();
public override object? GetEntity(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
FetchedUris.Add(absoluteUri);
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
} }
/***********************************************************/ /***********************************************************/

View file

@ -1019,7 +1019,8 @@ namespace System.Xml.Tests
} }
catch (System.Xml.Xsl.XsltCompileException e) 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; return;
} }
_output.WriteLine("Exception not thrown for null resolver"); _output.WriteLine("Exception not thrown for null resolver");
@ -1104,7 +1105,9 @@ namespace System.Xml.Tests
Assert.False(isEnabled); Assert.False(isEnabled);
var e = Assert.Throws<XsltCompileException>(() => LoadXSL("XmlResolver_Main.xsl", inputType, readerType)); var e = Assert.Throws<XsltCompileException>(() => LoadXSL("XmlResolver_Main.xsl", inputType, readerType));
var xmlException = Assert.IsType<XmlException>(e.InnerException); var xmlException = Assert.IsType<XmlException>(e.InnerException);
CheckExpectedError(xmlException, "System.Xml", "Xml_NullResolver", Array.Empty<string>());
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.")] //[Variation("Load with resolver with credentials, then load XSL that does not need cred.")]

View file

@ -393,4 +393,7 @@
<data name="WrongRootElement" xml:space="preserve"> <data name="WrongRootElement" xml:space="preserve">
<value>Root element must be {0} element in namespace {1}</value> <value>Root element must be {0} element in namespace {1}</value>
</data> </data>
<data name="Cryptography_Xml_EntityResolutionNotSupported" xml:space="preserve">
<value>External entity resolution is not supported.</value>
</data>
</root> </root>

View file

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks> <TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -126,6 +126,7 @@ System.Security.Cryptography.Xml.XmlLicenseTransform</PackageDescription>
<Compile Include="System\Security\Cryptography\Xml\XmlDsigXPathTransform.cs" /> <Compile Include="System\Security\Cryptography\Xml\XmlDsigXPathTransform.cs" />
<Compile Include="System\Security\Cryptography\Xml\XmlDsigXsltTransform.cs" /> <Compile Include="System\Security\Cryptography\Xml\XmlDsigXsltTransform.cs" />
<Compile Include="System\Security\Cryptography\Xml\XmlLicenseTransform.cs" /> <Compile Include="System\Security\Cryptography\Xml\XmlLicenseTransform.cs" />
<Compile Include="System\Security\Cryptography\Xml\XmlResolverHelper.cs" />
<Compile Include="System\Security\Cryptography\Xml\CryptoHelpers.cs" /> <Compile Include="System\Security\Cryptography\Xml\CryptoHelpers.cs" />
<Compile Include="System\Security\Cryptography\Xml\RSAPKCS1SignatureDescription.cs" /> <Compile Include="System\Security\Cryptography\Xml\RSAPKCS1SignatureDescription.cs" />
<Compile Include="System\Security\Cryptography\Xml\RSAPKCS1SHA1SignatureDescription.cs" /> <Compile Include="System\Security\Cryptography\Xml\RSAPKCS1SHA1SignatureDescription.cs" />

View file

@ -359,7 +359,7 @@ namespace System.Security.Cryptography.Xml
{ {
case ReferenceTargetType.Stream: case ReferenceTargetType.Stream:
// This is the easiest case. We already have a stream, so just pump it through the TransformChain // 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); hashInputStream = TransformChain.TransformToOctetStream((Stream)_refTarget, resolver, baseUri);
break; break;
case ReferenceTargetType.UriReference: case ReferenceTargetType.UriReference:
@ -369,7 +369,7 @@ namespace System.Security.Cryptography.Xml
if (_uri == null) if (_uri == null)
{ {
// We need to create a DocumentNavigator out of the 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());
// In the case of a Uri-less reference, we will simply pass null to the transform chain. // 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. // The first transform in the chain is expected to know how to retrieve the data to hash.
hashInputStream = TransformChain.TransformToOctetStream((Stream)null, resolver, baseUri); 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)); throw new CryptographicException(SR.Format(SR.Cryptography_Xml_SelfReferenceRequiresContext, _uri));
// Normalize the containing document // 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)); XmlDocument docWithNoComments = Utils.DiscardComments(Utils.PreProcessDocumentInput(document, resolver, baseUri));
hashInputStream = TransformChain.TransformToOctetStream(docWithNoComments, 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)); throw new CryptographicException(SR.Format(SR.Cryptography_Xml_SelfReferenceRequiresContext, _uri));
// We should not discard comments here!!! // 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); hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessDocumentInput(document, resolver, baseUri), resolver, baseUri);
break; break;
} }
@ -434,7 +434,7 @@ namespace System.Security.Cryptography.Xml
// Add the propagated attributes // Add the propagated attributes
Utils.AddNamespaces(normDocument.DocumentElement, _namespaces); Utils.AddNamespaces(normDocument.DocumentElement, _namespaces);
resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); resolver = (SignedXml.ResolverSet ? SignedXml._xmlResolver : XmlResolverHelper.GetThrowingResolver());
if (discardComments) if (discardComments)
{ {
// We should discard comments before going into the transform chain // We should discard comments before going into the transform chain
@ -454,7 +454,7 @@ namespace System.Security.Cryptography.Xml
break; break;
case ReferenceTargetType.XmlElement: case ReferenceTargetType.XmlElement:
// We need to create a DocumentNavigator out of the 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); hashInputStream = TransformChain.TransformToOctetStream(Utils.PreProcessElementInput((XmlElement)_refTarget, resolver, baseUri), resolver, baseUri);
break; break;
default: default:

View file

@ -775,7 +775,7 @@ namespace System.Security.Cryptography.Xml
if (isKeyedHashAlgorithm || !_bCacheValid || !SignedInfo.CacheValid) if (isKeyedHashAlgorithm || !_bCacheValid || !SignedInfo.CacheValid)
{ {
string baseUri = _containingDocument?.BaseURI; 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); XmlDocument doc = Utils.PreProcessElementInput(SignedInfo.GetXml(), resolver, baseUri);
// Add non default namespaces in scope // Add non default namespaces in scope

View file

@ -142,7 +142,7 @@ namespace System.Security.Cryptography.Xml
{ {
XmlDocument document = new XmlDocument(); XmlDocument document = new XmlDocument();
document.PreserveWhitespace = true; 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); XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
document.Load(xmlReader); document.Load(xmlReader);
_containingDocument = document; _containingDocument = document;

View file

@ -47,7 +47,7 @@ namespace System.Security.Cryptography.Xml
public override void LoadInput(object obj) 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) if (obj is Stream)
{ {
_cXml = new CanonicalXml((Stream)obj, _includeComments, resolver, BaseURI); _cXml = new CanonicalXml((Stream)obj, _includeComments, resolver, BaseURI);

View file

@ -79,7 +79,7 @@ namespace System.Security.Cryptography.Xml
{ {
XmlDocument doc = new XmlDocument(); XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true; 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); XmlReader xmlReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
doc.Load(xmlReader); doc.Load(xmlReader);
_containingDocument = doc; _containingDocument = doc;

View file

@ -74,7 +74,7 @@ namespace System.Security.Cryptography.Xml
public override void LoadInput(object obj) 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) if (obj is Stream)
{ {
_excCanonicalXml = new ExcCanonicalXml((Stream)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver, BaseURI); _excCanonicalXml = new ExcCanonicalXml((Stream)obj, _includeComments, _inclusiveNamespacesPrefixList, resolver, BaseURI);

View file

@ -133,7 +133,7 @@ namespace System.Security.Cryptography.Xml
private void LoadStreamInput(Stream stream) 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); XmlReader valReader = Utils.PreProcessStreamInput(stream, resolver, BaseURI);
_document = new XmlDocument(); _document = new XmlDocument();
_document.PreserveWhitespace = true; _document.PreserveWhitespace = true;
@ -143,7 +143,7 @@ namespace System.Security.Cryptography.Xml
private void LoadXmlNodeListInput(XmlNodeList nodeList) private void LoadXmlNodeListInput(XmlNodeList nodeList)
{ {
// Use C14N to get a document // 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); CanonicalXml c14n = new CanonicalXml((XmlNodeList)nodeList, resolver, true);
using (MemoryStream ms = new MemoryStream(c14n.GetBytes())) using (MemoryStream ms = new MemoryStream(c14n.GetBytes()))
{ {

View file

@ -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<object> GetEntityAsync(Uri absoluteUri, string? role, Type? ofObjectToReturn)
{
throw new XmlException(SR.Cryptography_Xml_EntityResolutionNotSupported);
}
}
#endif
}
}

View file

@ -11,8 +11,11 @@
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml; using System.Xml;
using System.Xml.XPath; using System.Xml.XPath;
using Test.Cryptography; using Test.Cryptography;
@ -1587,6 +1590,127 @@ namespace System.Security.Cryptography.Xml.Tests
Assert.Throws<FormatException>(() => sign.CheckSignature(new HMACSHA1("no clue"u8.ToArray()))); Assert.Throws<FormatException>(() => 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 = $@"<!DOCTYPE foo [<!ENTITY xxe SYSTEM ""http://127.0.0.1:{port}/"" >]>
<ExampleDoc>Example doc to be signed.&xxe;<Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
<SignedInfo>
<CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315"" />
<SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"" />
<Reference URI="""">
<Transforms>
<Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature"" />
</Transforms>
<DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256"" />
<DigestValue>CLUSJx4H4EwydAT/CtNWYu/l6R8uZe0tO2rlM/o0iM4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>o0IAVyovNUYKs5CCIRpZVy6noLpdJBp8LwWrqzzhKPg=</SignatureValue>
</Signature>
</ExampleDoc>";
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<XmlException>(() => signedXml.CheckSignature(key));
Assert.False(listenerContacted, "listenerContacted");
}
}
}
finally
{
tokenSource.Cancel();
try
{
listener.Stop();
}
catch
{
}
((IDisposable)listener).Dispose();
}
static async Task ProcessRequests(
HttpListener listener,
Action<HttpListenerRequest> 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] [Fact]
public void CoreFxSignedXmlUsesSha256ByDefault() public void CoreFxSignedXmlUsesSha256ByDefault()
{ {

View file

@ -948,11 +948,13 @@ namespace System.Xml
{ {
protected XmlResolver() { } protected XmlResolver() { }
public virtual System.Net.ICredentials Credentials { set { } } 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 abstract object? GetEntity(System.Uri absoluteUri, string? role, System.Type? ofObjectToReturn);
public virtual System.Threading.Tasks.Task<object> GetEntityAsync(System.Uri absoluteUri, string? role, System.Type? ofObjectToReturn) { throw null; } public virtual System.Threading.Tasks.Task<object> 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 System.Uri ResolveUri(System.Uri? baseUri, string? relativeUri) { throw null; }
public virtual bool SupportsType(System.Uri absoluteUri, System.Type? type) { 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 partial class XmlSecureResolver : System.Xml.XmlResolver
{ {
public XmlSecureResolver(System.Xml.XmlResolver resolver, string? securityUrl) { } public XmlSecureResolver(System.Xml.XmlResolver resolver, string? securityUrl) { }