Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix xml signature verification and update to .net 9.0 #19

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 7.x
dotnet-version: 9.x
- name: Restore dependencies
run: dotnet restore
working-directory: CIE.AspNetCore.Authentication
Expand All @@ -44,7 +44,7 @@ jobs:
- name: Update apt repo
run: sudo apt update
- name: Install dependencies
run: sudo apt install -y libxml2-dev libxmlsec1-dev libxmlsec1-openssl xmlsec1 python3-pip && pip install cryptography==38.0.4
run: sudo apt install -y libxml2-dev libxmlsec1-dev libxmlsec1-openssl xmlsec1 python3-pip
- name: Install spid-sp-test
run: sudo pip install spid-sp-test --upgrade --no-cache
- name: Test Metadata cie-sp-public with spid-sp-test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net7.0;net6.0;net5.0</TargetFrameworks>
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Description>AspNetCore Remote Authenticator for CIE</Description>
<Authors>Daniele Giallonardo, Stefano Mostarda</Authors>
Expand All @@ -12,42 +12,42 @@
<PackageProjectUrl>https://github.com/italia/cie-aspnetcore</PackageProjectUrl>
<PackageIcon>cie-nuget.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageVersion>2.0.4</PackageVersion>
<Version>2.0.4</Version>
<AssemblyVersion>2.0.4</AssemblyVersion>
<FileVersion>2.0.4</FileVersion>
<InformationalVersion>2.0.4</InformationalVersion>
<PackageVersion>2.0.5</PackageVersion>
<Version>2.0.5</Version>
<AssemblyVersion>2.0.5</AssemblyVersion>
<FileVersion>2.0.5</FileVersion>
<InformationalVersion>2.0.5</InformationalVersion>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/italia/cie-aspnetcore</RepositoryUrl>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.21" />
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="9.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.1" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="7.0.1" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="8.0.12" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net7.0' ">
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.10" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="7.0.12" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="6.0.21" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net5.0' ">
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="5.0.17" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using CIE.AspNetCore.Authentication.Resources;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.Xml.Serialization;

namespace CIE.AspNetCore.Authentication.Helpers
{
Expand Down Expand Up @@ -36,7 +34,7 @@

try
{
privateKey = certificate.PrivateKey;
privateKey = certificate.GetRSAPrivateKey();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -80,11 +78,9 @@

try
{
SignedXml signedXml = new SignedXml(signedDocument);

if (xmlMetadata is not null)
{
bool validated = false;
var validated = false;
var idpSSODescriptor = xmlMetadata.Items.FirstOrDefault(i => i is Saml.IdP.IDPSSODescriptorType) as Saml.IdP.IDPSSODescriptorType;
if (idpSSODescriptor is not null)
{
Expand All @@ -96,14 +92,7 @@
var x509Cert = keyData.Items.FirstOrDefault(i => i is byte[]) as byte[];
if (x509Cert is not null)
{
var publicMetadataCert = new X509Certificate2(x509Cert);
XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 1) ?
signedDocument.GetElementsByTagName("ds:Signature") :
(signedDocument.GetElementsByTagName("ns2:Signature")?.Count > 1) ?
signedDocument.GetElementsByTagName("ns2:Signature") :
signedDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
validated |= signedXml.CheckSignature(publicMetadataCert, true);
validated |= VerifyAllSignatures(signedDocument, new X509Certificate2(x509Cert));
}
}
}
Expand All @@ -112,11 +101,7 @@
}
else
{
XmlNodeList nodeList = (signedDocument.GetElementsByTagName("ds:Signature")?.Count > 0) ?
signedDocument.GetElementsByTagName("ds:Signature") :
signedDocument.GetElementsByTagName("Signature");
signedXml.LoadXml((XmlElement)nodeList[0]);
return signedXml.CheckSignature();
return VerifyAllSignatures(signedDocument);
}
}
catch (Exception)
Expand All @@ -125,64 +110,26 @@
}
}

private static readonly ConcurrentDictionary<Type, XmlSerializer> serializers = new ConcurrentDictionary<Type, XmlSerializer>();
/// <summary>
/// Serializes to XML document.
/// </summary>
/// <param name="o">The o.</param>
/// <returns></returns>
public static XmlDocument SerializeToXmlDoc(this object o)
private static bool VerifyAllSignatures(XmlDocument signedDocument, X509Certificate2? publicMetadataCert = null)

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 113 in CIE.AspNetCore.Authentication/CIE.AspNetCore.Authentication/Helpers/XmlHelpers.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
XmlDocument doc = new XmlDocument() { PreserveWhitespace = true };
bool internalResult = true;

XmlNodeList signatureNodes = signedDocument.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl);

using XmlWriter writer = doc.CreateNavigator().AppendChild();
if (!serializers.ContainsKey(o.GetType()))
if (signatureNodes.Count == 0)
{
var serializer = new XmlSerializer(o.GetType());
serializers.AddOrUpdate(o.GetType(), serializer, (key, value) => serializer);
return false;
}
serializers[o.GetType()].Serialize(writer, o);

return doc;
}

public static XmlElement SerializeInternalExtensionToXmlElement(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = SerializeExtensionToXmlElementInternal(o, namespacePrefix, xmlNamespace);

return doc.DocumentElement.FirstChild as XmlElement;
}

public static XmlElement SerializeExtensionToXmlElement(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = SerializeExtensionToXmlElementInternal(o, namespacePrefix, xmlNamespace);

return doc.DocumentElement;
}

private static XmlDocument SerializeExtensionToXmlElementInternal(object o, string namespacePrefix, string xmlNamespace)
{
XmlDocument doc = new XmlDocument();

using (XmlWriter writer = doc.CreateNavigator().AppendChild())
foreach (var signatureNode in signatureNodes)
{
var ns = new XmlSerializerNamespaces();
ns.Add(namespacePrefix, xmlNamespace);
new XmlSerializer(o.GetType()).Serialize(writer, o, ns);
SignedXml signedXml = new(signedDocument);
signedXml.LoadXml((XmlElement)signatureNode);
internalResult &= publicMetadataCert is null
? signedXml.CheckSignature()
: signedXml.CheckSignature(publicMetadataCert, true);
}

return doc;
}

public static XmlElement GetXmlElement(string prefix, string prefixNamespace, string tag, string value = null)
{
XmlDocument doc = new XmlDocument();

XmlElement elem = doc.CreateElement(prefix, tag, prefixNamespace);
if(!string.IsNullOrEmpty(value))
elem.InnerText = value;

return elem;
return internalResult;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
<UserSecretsId>b637b4cd-be76-4dc7-851e-b721746073a1</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="7.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading