Skip to content

X509Chain does not populate ChainElements (Android) #84202

@borrrden

Description

@borrrden

Description

I am using SslStream with a remote certificate validation callback on many platforms. The only one that has an issue is .NET 6 Android (Xamarin Android is OK, FYI). I am already painfully aware of this issue which is currently kneecapping the custom certificate validation of our SDK, but I did find a way to work around that by forcing Android to trust my cert using network-security-config.

That being said, now that the callback is finally being called, the chain argument has 0 elements. On .NET 6 Console, it is properly populated with 3 elements. I also saw this happen on Xamarin / Mono back in the day but as a workaround I would take the received cert and use X509Chain.Build() to reconstruct the chain so that I could examine it. The problem is that on .NET 6 Android this also does not work. The resulting chain still has 0 elements.

Reproduction Steps

I'm unsure of how I could present this because it requires a server running https using a cert that is not trusted by stock Android, but assuming that such a server is running these are the steps to take:

  1. Start server (In my case I have the server set up to serve the entire chain, but not sure if this is required or not)

  2. Create a maui project (or .NET 6 Android at least)

  3. Add the cert that the server is using (not sure if the whole chain is needed or not, but I used a PEM file with the three concatenated certificates inside) to Resources/raw/cert.pem

  4. Add the following as Resources/xml/network_security_config.xml

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="@raw/cert"/>
            <certificates src="system"/>
        </trust-anchors>
    </base-config>
</network-security-config>
  1. Annotate the MauiApplication with the following: [Application(NetworkSecurityConfig = "@xml/network_security_config")]
  2. Open a TcpClient to the server in question (_client.ConnectAsync(host, port))
  3. Wrap the TCP client in SslStream -> var sslStream = new SslStream(_client.GetStream(), false, ValidateServerCert);
  4. Implement ValidateServerCert with simply return true or anything you want
  5. Call sslStream.AuthenticateAsClientAsync(host, null, SslProtocols.Tls12, false)
  6. Inspect the third argument of ValidateServerCert

Expected behavior

The chain passed into the validation callback with the proper ChainElements

Actual behavior

ChainElements is length 0

Regression?

Not sure how to categorize this but at least with the mono workaround in place this works on the following platforms:

  • .NET 6 Windows Console
  • .NET 6 WinUI
  • .NET 6 iOS
  • .NET 6 Mac Catalyst
  • Xamarin iOS
  • Xamarin Android
  • .NET Framework 4.6.2

Known Workarounds

Unknown at this time

Configuration

.NET 6 on Android API 26 x64 emulator

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions