< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 75
Coverable lines: 75
Total lines: 131
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 38
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

D:\runner\runtime\src\libraries\Common\src\System\Net\Security\CertificateHelper.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Globalization;
 6using System.Security.Cryptography;
 7using System.Security.Cryptography.X509Certificates;
 8using Microsoft.Win32.SafeHandles;
 9
 10namespace System.Net.Security
 11{
 12    internal static partial class CertificateHelper
 13    {
 14        private const string ClientAuthenticationOID = "1.3.6.1.5.5.7.3.2";
 15
 16        internal static X509Certificate2? GetEligibleClientCertificate(X509CertificateCollection? candidateCerts)
 017        {
 018            if (candidateCerts == null || candidateCerts.Count == 0)
 019            {
 020                return null;
 21            }
 22
 023            var certs = new X509Certificate2Collection();
 024            certs.AddRange(candidateCerts);
 25
 026            return GetEligibleClientCertificate(certs);
 027        }
 28
 29        internal static X509Certificate2? GetEligibleClientCertificate(X509Certificate2Collection? candidateCerts)
 030        {
 031            if (candidateCerts == null || candidateCerts.Count == 0)
 032            {
 033                return null;
 34            }
 35
 036            foreach (X509Certificate2 cert in candidateCerts)
 037            {
 038                if (!cert.HasPrivateKey)
 039                {
 040                    if (NetEventSource.Log.IsEnabled())
 041                    {
 042                        NetEventSource.Info(candidateCerts, $"Skipping current X509Certificate2 {cert.GetHashCode()} sin
 043                    }
 044                    continue;
 45                }
 46
 047                if (IsValidClientCertificate(cert))
 048                {
 049                    if (NetEventSource.Log.IsEnabled())
 050                    {
 051                        NetEventSource.Info(candidateCerts, $"Choosing X509Certificate2 {cert.GetHashCode()} as the Clie
 052                    }
 053                    return cert;
 54                }
 055            }
 56
 057            if (NetEventSource.Log.IsEnabled())
 058            {
 059                NetEventSource.Info(candidateCerts, "No eligible client certificate found.");
 060            }
 061            return null;
 062        }
 63
 64        private static bool IsValidClientCertificate(X509Certificate2 cert)
 065        {
 066            foreach (X509Extension extension in cert.Extensions)
 067            {
 068                if ((extension is X509EnhancedKeyUsageExtension eku) && !IsValidForClientAuthenticationEKU(eku))
 069                {
 070                    if (NetEventSource.Log.IsEnabled())
 071                    {
 072                        NetEventSource.Info(cert, $"For Certificate {cert.GetHashCode()} - current X509EnhancedKeyUsageE
 073                    }
 074                    return false;
 75                }
 076                else if ((extension is X509KeyUsageExtension ku) && !IsValidForDigitalSignatureUsage(ku))
 077                {
 078                    if (NetEventSource.Log.IsEnabled())
 079                    {
 080                        NetEventSource.Info(cert, $"For Certificate {cert.GetHashCode()} - current X509KeyUsageExtension
 081                    }
 082                    return false;
 83                }
 084            }
 85
 086            return true;
 087        }
 88
 89        private static bool IsValidForClientAuthenticationEKU(X509EnhancedKeyUsageExtension eku)
 090        {
 091            foreach (Oid oid in eku.EnhancedKeyUsages)
 092            {
 093                if (oid.Value == ClientAuthenticationOID)
 094                {
 095                    return true;
 96                }
 097            }
 98
 099            return false;
 0100        }
 101
 102        private static bool IsValidForDigitalSignatureUsage(X509KeyUsageExtension ku)
 0103        {
 104            const X509KeyUsageFlags RequiredUsages = X509KeyUsageFlags.DigitalSignature;
 0105            return (ku.KeyUsages & RequiredUsages) == RequiredUsages;
 0106        }
 107    }
 108}

D:\runner\runtime\src\libraries\Common\src\System\Net\Security\CertificateHelper.Windows.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Security.Cryptography.X509Certificates;
 5
 6namespace System.Net.Security
 7{
 8    internal static partial class CertificateHelper
 9    {
 10        internal static X509Certificate2? GetEligibleClientCertificate()
 011        {
 12            // Get initial list of client certificates from the MY store.
 13            X509Certificate2Collection candidateCerts;
 014            using (var myStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
 015            {
 016                myStore.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
 017                candidateCerts = myStore.Certificates;
 018            }
 19
 020            return GetEligibleClientCertificate(candidateCerts);
 021        }
 22    }
 23}