mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 10:00:57 +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:
parent
f44da5225f
commit
d2afae4fb0
36 changed files with 474 additions and 124 deletions
|
@ -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. |
|
||||
| __`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. |
|
||||
| __`SYSLIB0047`__ | XmlSecureResolver is obsolete. Use XmlResolver.ThrowingResolver instead when attempting to forbid XML external entity resolution. |
|
||||
|
||||
## Analyzer Warnings
|
||||
|
||||
|
|
|
@ -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 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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -514,7 +514,7 @@
|
|||
<value>Object type is not supported.</value>
|
||||
</data>
|
||||
<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 name="Xml_RelativeUriNotSupported" xml:space="preserve">
|
||||
<value>Relative URIs are not supported.</value>
|
||||
|
|
|
@ -127,13 +127,11 @@
|
|||
<Compile Include="System\Xml\XmlNameTable.cs" />
|
||||
<Compile Include="System\Xml\XmlNodeOrder.cs" />
|
||||
<Compile Include="System\Xml\XmlNodeType.cs" />
|
||||
<Compile Include="System\Xml\XmlNullResolver.cs" />
|
||||
<Compile Include="System\Xml\XmlQualifiedName.cs" />
|
||||
<Compile Include="System\Xml\XmlReservedNs.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\XmlSecureResolverAsync.cs" />
|
||||
<Compile Include="System\Xml\XmlUrlResolver.cs" />
|
||||
<Compile Include="System\Xml\XmlUrlResolverAsync.cs" />
|
||||
<Compile Include="System\Xml\Core\CharEntityEncoderFallback.cs" />
|
||||
|
@ -748,6 +746,7 @@
|
|||
<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.AppendSpanFormattable.cs" Link="Common\System\Text\ValueStringBuilder.AppendSpanFormattable.cs" />
|
||||
<Compile Include="$(CommonPath)System\Obsoletions.cs" Link="Common\System\Obsoletions.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
|
||||
|
|
|
@ -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 */ }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,12 @@ namespace System.Xml
|
|||
string? role,
|
||||
Type? ofObjectToReturn);
|
||||
|
||||
|
||||
public virtual Task<object> GetEntityAsync(Uri absoluteUri,
|
||||
string? role,
|
||||
Type? ofObjectToReturn)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>[To be supplied.]</para>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<object> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -405,7 +408,7 @@ namespace System.Xml.Xsl
|
|||
return new XmlUrlResolver();
|
||||
}
|
||||
|
||||
return XmlNullResolver.Singleton;
|
||||
return XmlResolver.ThrowingResolver;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="XmlThrowingResolverTests.cs" />
|
||||
<Compile Include="XmlSecureResolverTests.cs" />
|
||||
<Compile Include="XmlUrlResolverTests.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,12 +86,6 @@ namespace System.Xml.Tests
|
|||
_resolver = new XmlUrlResolver();
|
||||
}
|
||||
|
||||
public CXmlTestResolver(string securityUri)
|
||||
: base()
|
||||
{
|
||||
_resolver = new XmlSecureResolver(new XmlUrlResolver(), securityUri);
|
||||
}
|
||||
|
||||
// -----------------
|
||||
// Events
|
||||
// -----------------
|
||||
|
|
|
@ -98,6 +98,6 @@
|
|||
<!-- XML Exceptions -->
|
||||
<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_NullResolver" message="Resolving of external URIs was prohibited. "/>
|
||||
<exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. Attempted access to: {0}"/>
|
||||
|
||||
</exceptions>
|
|
@ -101,6 +101,6 @@
|
|||
<!-- XML Exceptions -->
|
||||
<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_NullResolver" message="Resolving of external URIs was prohibited. "/>
|
||||
<exception res="Xml_NullResolver" message="Resolving of external URIs was prohibited. Attempted access to: {0}"/>
|
||||
|
||||
</exceptions>
|
|
@ -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<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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
|
|
|
@ -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<XsltCompileException>(() => LoadXSL("XmlResolver_Main.xsl", inputType, readerType));
|
||||
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.")]
|
||||
|
|
|
@ -393,4 +393,7 @@
|
|||
<data name="WrongRootElement" xml:space="preserve">
|
||||
<value>Root element must be {0} element in namespace {1}</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="Cryptography_Xml_EntityResolutionNotSupported" xml:space="preserve">
|
||||
<value>External entity resolution is not supported.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
|
||||
<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\XmlDsigXsltTransform.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\RSAPKCS1SignatureDescription.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Xml\RSAPKCS1SHA1SignatureDescription.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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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<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]
|
||||
public void CoreFxSignedXmlUsesSha256ByDefault()
|
||||
{
|
||||
|
|
|
@ -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<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 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) { }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue