RemoteCertificateValidationCallback Delegate

public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors);

Represents a method that validates a server's X.509 certificate.

The RemoteCertificateValidationCallback delegate is used to provide a custom validation procedure for the server certificate during an SSL/TLS connection. When a client connects to a server using a protocol that relies on SSL/TLS (like HTTPS), the server presents its certificate. The default validation process checks if the certificate is trusted, has not expired, and matches the hostname. However, in certain scenarios, you might need to implement more specific or lenient validation logic. This delegate allows you to hook into that process and return your own decision on whether the certificate is acceptable.

Syntax

public delegate bool RemoteCertificateValidationCallback( object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors );

Parameters

Parameter Description
sender The object that initiated the callback. This is typically an instance of System.Net.Security.SslStream.
certificate The X.509 certificate that was presented by the server. This can be null if the server did not provide a certificate.
chain The chain of certificates, built from the server certificate up to a trusted root. This can be null if the server did not provide a certificate or if certificate chain building failed.
sslPolicyErrors A bitwise combination of enumeration values that specifies the errors encountered during certificate validation.

Return Value

true if the certificate is valid and the connection should proceed; otherwise, false.

Remarks

The RemoteCertificateValidationCallback delegate is assigned to the RemoteCertificateValidationCallback property of the System.Net.Security.SslStream class. When an SSL/TLS connection is established, and the server presents its certificate, the SslStream invokes the callback method.

Inside your callback implementation, you should inspect the provided parameters:

If your callback returns true, the SSL/TLS handshake continues. If it returns false, the handshake fails, and the connection is terminated.

Security Warning: Overriding the default certificate validation logic can expose your application to significant security risks, such as man-in-the-middle attacks. Only implement a custom validator if you fully understand the implications and have a specific, well-justified reason to deviate from standard validation practices. In most production scenarios, relying on the default validation is recommended.

Example

The following example demonstrates how to use a custom RemoteCertificateValidationCallback to allow connections even if the server certificate has SSL policy errors (e.g., self-signed certificates in a test environment). This is not recommended for production use.

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) { using (var client = new TcpClient()) { await client.ConnectAsync(host, port); using (var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate)) { try { // Authenticate as client await sslStream.AuthenticateAsClientAsync(host); // Read/Write data... Console.WriteLine("SSL connection established successfully."); } catch (Exception ex) { Console.WriteLine($"Authentication failed: {ex.Message}"); } } } } // Custom validation callback - WARNING: Insecure for production! public static bool ValidateServerCertificate(object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) { Console.WriteLine($"Certificate validation errors: {sslPolicyErrors}"); // In a real application, you would perform more robust checks here. // For demonstration purposes, we'll allow connections even if there are errors. // NEVER do this in production code without extremely careful consideration. if (sslPolicyErrors == SslPolicyErrors.None) { return true; // Certificate is valid } // Example: Accept self-signed certificates or certificates with other issues // if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) || // sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch)) // { // // Log the issue and decide if it's acceptable in your context // Console.WriteLine("Warning: Allowing connection despite certificate errors."); // return true; // For demonstration, accept these errors // } // For this example, we will simply return true to allow the connection regardless of errors. // This is HIGHLY INSECURE and should not be used in production. Console.WriteLine("Accepting certificate despite potential policy errors (INSECURE)."); return true; } // Example usage: // public static async Task Main(string[] args) // { // // Replace with a real server host and port that uses SSL/TLS // // await ConnectAsync("your.ssl.server.com", 443); // } }

See Also