MSDN Library

System.Net.Security.SslValidationCallback Delegate

Represents the method that handles validation of an SSL certificate.

Syntax

public delegate bool SslValidationCallback(
    object sender,
    string targetHost,
    X509Certificate2 certificate,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors
);

Parameters

Parameter Type Description
sender object The object that initiated the callback. Typically, this is an instance of the System.Net.Security.SslStream class.
targetHost string The name of the host that the client is attempting to authenticate.
certificate System.Security.Cryptography.X509Certificates.X509Certificate2 The certificate used to authenticate the remote end of the connection.
chain System.Security.Cryptography.X509Certificates.X509Chain The chain of certificates that was created to authenticate the server.
sslPolicyErrors System.Net.Security.SslPolicyErrors One or more errors that occurred during certificate validation.

Return Value

Type Description
bool true if the certificate is trusted; otherwise, false.

Remarks

The SslValidationCallback delegate is used by the System.Net.Security.SslStream class to validate the server's certificate during an SSL/TLS handshake.

When you create an instance of SslStream and call its AuthenticateAsClient method, you can provide a delegate to the remoteCertValidationCallback parameter. This delegate will be invoked whenever the SslStream needs to validate the server's certificate.

The callback method you provide should examine the provided parameters, especially sslPolicyErrors, to determine if the certificate is acceptable. If the certificate is considered valid for your application's needs, the callback should return true. Otherwise, it should return false.

Important: In production environments, it is generally recommended to perform thorough certificate validation to ensure the security of your application. Relying solely on returning true when sslPolicyErrors is not SslPolicyErrors.None can expose your application to security risks.

Note: Custom certificate validation logic should be carefully designed and tested to avoid security vulnerabilities.

Example

C# Example
using System;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

public class SslClient
{
    public static async Task ConnectAsync(string host, int port)
    {
        try
        {
            using (var client = new TcpClient())
            {
                await client.ConnectAsync(host, port);
                using (var sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null))
                {
                    // Authenticate the client.
                    await sslStream.AuthenticateAsClientAsync(host);

                    // The certificate has been authenticated.
                    Console.WriteLine("SSL connection established.");
                    // You can now send and receive data using sslStream.
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }

    public static bool ValidateServerCertificate(object sender, string targetHost, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        // In a production environment, you should validate the certificate carefully.
        // For this example, we'll allow any certificate if there are no errors.
        // If there are errors, we'll log them but still might accept it for demonstration.

        Console.WriteLine($"Certificate validation requested for host: {targetHost}");
        Console.WriteLine($"Certificate subject: {certificate.Subject}");

        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            Console.WriteLine("Certificate validation successful (no errors).");
            return true; // Certificate is trusted.
        }

        Console.WriteLine($"Certificate validation encountered errors: {sslPolicyErrors}");

        // You might want to implement more specific checks here, like:
        // 1. Checking if the certificate's issuer is trusted.
        // 2. Checking if the certificate's expiration date is valid.
        // 3. Checking if the certificate's subject name matches the target host.
        // 4. Checking for revocation status.

        // For demonstration purposes, we'll allow it if it's not a certificate name mismatch.
        if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
        {
            Console.WriteLine("Certificate name mismatch. Rejecting connection.");
            return false;
        }

        // You might decide to trust other errors based on your application's security policy.
        // For this example, let's assume we accept if it's not a name mismatch.
        // In a real application, this is a security risk.
        Console.WriteLine("Allowing certificate despite policy errors (for demonstration).");
        return true; // Potentially insecure - adjust for production.
    }

    // Example of how to call ConnectAsync
    // public static async Task Main(string[] args)
    // {
    //     await ConnectAsync("www.example.com", 443);
    // }
}

Requirements

Namespace: System.Net.Security

Assembly: System.Net.Primitives.dll (in .NET Core and .NET 5+)

Assembly: System.dll (in .NET Framework)

See Also