.NET API Documentation

LocalCertificateValidationCallback

Represents a callback method that is used to validate a local certificate.

Delegate

This delegate is used to customize the validation of local certificates when using SSL/TLS connections. It allows you to implement custom logic for determining whether a local certificate is acceptable for establishing a secure connection.

Syntax


public delegate bool LocalCertificateValidationCallback(
    object sender,
    X509Certificate certificate,
    X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors
);
            

Parameters

Parameter Description
sender The object that initiated the certificate validation callback. This is typically an instance of SslStream or a derived class.
certificate The local certificate that is being validated. This is an instance of the X509Certificate class.
chain The certificate chain associated with the local certificate. This is an instance of the X509Chain class.
sslPolicyErrors A bitwise combination of the enumeration values that indicate errors in the certificate validation. If no errors occurred, this value is SslPolicyErrors.None.

Return Value

true if the certificate is valid; otherwise, false.

Remarks

The LocalCertificateValidationCallback delegate is invoked by the .NET Framework when it needs to validate a local certificate for an SSL/TLS connection. You can assign a method that matches the signature of this delegate to the LocalCertificateValidationCallback property of an SslClientAuthenticationOptions or SslServerAuthenticationOptions object to provide custom validation logic.

When implementing your callback method, you should examine the provided X509Certificate, X509Chain, and SslPolicyErrors to determine the validity of the certificate. If you return true, the certificate is considered valid, and the connection can proceed. If you return false, the connection will be aborted.

It is crucial to handle potential errors indicated by sslPolicyErrors appropriately. For example, you might choose to allow connections even if there are some minor policy errors, depending on your application's security requirements. However, be cautious when ignoring security-related errors.

Example

Custom Local Certificate Validation

The following example demonstrates how to create and use a custom LocalCertificateValidationCallback to validate a local certificate.


using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Net.Sockets;

public class CustomCertificateValidator
{
    public static void Main(string[] args)
    {
        // Example usage within a client scenario
        TcpClient client = new TcpClient();
        try
        {
            client.Connect("server.example.com", 443);
            using (SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), new LocalCertificateSelectionCallback(SelectLocalCertificate)))
            {
                // For demonstration purposes, we'll provide a dummy local certificate
                X509Certificate2 localCert = GetLocalCertificate(); // Implement this method to load your actual certificate

                // Set the local certificate for the SSL stream
                sslStream.AuthenticateAsClient("server.example.com", localCert, System.Security.Authentication.SslProtocols.Tls12, false);

                Console.WriteLine("SSL connection established successfully.");

                // ... perform secure communication ...
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
    }

    // Custom callback for validating the server's certificate (not the focus here, but often used together)
    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            return true;
        }
        Console.WriteLine($"Server certificate errors: {sslPolicyErrors}");
        // For this example, we'll still trust the server if there are errors, which is generally NOT recommended for production.
        // In a real application, you would implement more robust validation here.
        return true;
    }

    // Custom callback for selecting a local certificate
    public static X509Certificate SelectLocalCertificate(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remotelCertificate, string[] acceptableIssuers)
    {
        // In a real application, you would select the most appropriate certificate from the collection.
        // For this example, we'll just return the first one if available, or null.
        if (localCertificates != null && localCertificates.Count > 0)
        {
            Console.WriteLine("Selecting a local certificate.");
            return localCertificates[0];
        }
        Console.WriteLine("No local certificates found.");
        return null;
    }

    // Placeholder for loading a local certificate
    private static X509Certificate2 GetLocalCertificate()
    {
        try
        {
            // Replace with your certificate's path and password
            // Example: X509Certificate2 cert = new X509Certificate2("path/to/your/certificate.pfx", "your_password");
            // For demonstration, we'll create a self-signed certificate in memory.
            // THIS IS NOT SECURE FOR PRODUCTION USE.
            return CreateSelfSignedCertificate();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error loading local certificate: {ex.Message}");
            return null;
        }
    }

    // Helper method to create a dummy self-signed certificate for demonstration.
    private static X509Certificate2 CreateSelfSignedCertificate()
    {
        System.Security.Cryptography.ECDsa key = ECDsa.Create();
        CertificateRequest certTemplate = new CertificateRequest(
            "CN=MyLocalClientAuthCert",
            key,
            System.Security.Cryptography.HashAlgorithmName.SHA256);

        certTemplate.CertificateExtensions.Add(
            new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, false));

        DateTimeOffset notBefore = DateTimeOffset.UtcNow;
        DateTimeOffset notAfter = notBefore.AddYears(1);

        X509Certificate2 cert = certTemplate.CreateSelfSigned(notBefore, notAfter);

        // Note: For actual client authentication, the certificate needs to be properly managed
        // and potentially imported into the certificate store.
        Console.WriteLine("Created a dummy self-signed certificate.");
        return cert;
    }
}