SSLStreamErrorCallback Delegate

Namespace: System.Net.Security

Assembly: System.Net.Security.dll

Overview

Represents a method that will handle an error that occurred during SSL/TLS stream operations.

This delegate is used by the SslStream.AuthenticateAsClient and SslStream.AuthenticateAsServer methods to notify the caller when an error occurs during the authentication process or subsequent stream operations that are related to SSL/TLS. The callback method provides details about the error encountered.

Syntax


public delegate void SSLStreamErrorCallback(
    object sender,
    SSLStreamAsyncErrorEventArgs e
);
            

Parameters

sender
The object that raised the event. Typically, this is the SslStream object itself.
e
A SSLStreamAsyncErrorEventArgs object that contains the error information.

Remarks

The SSLStreamErrorCallback delegate is an asynchronous callback. The method you provide as the callback will be invoked on a thread pool thread when an error occurs. Ensure that your callback method is thread-safe.

The SSLStreamAsyncErrorEventArgs object passed to the callback contains information about the error, including the exception that occurred.

If an error occurs during SSL/TLS operations, the stream may become unusable. It is generally recommended to close the stream and re-establish the connection if an error is reported.

Example

The following C# code demonstrates how to register an SSLStreamErrorCallback delegate with an SslStream object.


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

public class SslClientExample {

    public static async Task ConnectAndAuthenticateAsync(string host, int port) {
        using (var client = new TcpClient()) {
            await client.ConnectAsync(host, port);

            using (var networkStream = client.GetStream())
            using (var sslStream = new SslStream(
                networkStream,
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                new LocalCertificateSelectionCallback(SelectClientCertificate)
            )) {
                sslStream.EncryptionPolicy = EncryptionPolicy.RequireEncryption;

                // Register the error callback
                sslStream.SetAsyncErrorCallback(new SSLStreamErrorCallback(HandleSslStreamError));

                try {
                    // For a client, you typically don't provide a server certificate.
                    // The RemoteCertificateValidationCallback handles validation.
                    await sslStream.AuthenticateAsClientAsync(host);

                    // If authentication is successful, proceed with sending/receiving data...
                    Console.WriteLine("Authentication successful.");

                    // Example: Send a message
                    byte[] message = System.Text.Encoding.UTF8.GetBytes("Hello from client!");
                    await sslStream.WriteAsync(message, 0, message.Length);
                    await sslStream.FlushAsync();

                    // Example: Read a response
                    byte[] buffer = new byte[2048];
                    int bytesRead = await sslStream.ReadAsync(buffer, 0, buffer.Length);
                    Console.WriteLine("Received: {0}", System.Text.Encoding.UTF8.GetString(buffer, 0, bytesRead));

                } catch (Exception ex) {
                    Console.WriteLine("An error occurred during SSL/TLS operation: {0}", ex.Message);
                }
            }
        }
    }

    // Callback to validate the server's certificate
    public static bool ValidateServerCertificate(
        object sender,
        X509Certificate? certificate,
        X509Chain? chain,
        SslPolicyErrors sslPolicyErrors) {

        if (sslPolicyErrors == SslPolicyErrors.None) {
            return true;
        }

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
        // In a real-world scenario, you would implement more robust validation here.
        // For demonstration, we'll allow it if there are no other errors.
        return false;
    }

    // Callback to select a client certificate (if required by the server)
    public static X509Certificate? SelectClientCertificate(
        object sender,
        string targetHost,
        X509CertificateCollection localCertificates,
        X509Certificate? remoteCertificate,
        string[] acceptableIssuers) {

        // In a real-world scenario, you would select an appropriate client certificate here.
        // For this example, we'll return null, meaning no client certificate is offered.
        return null;
    }

    // The SSLStreamErrorCallback method
    public static void HandleSslStreamError(
        object sender,
        SSLStreamAsyncErrorEventArgs e) {

        Console.WriteLine("SSLStreamErrorCallback invoked!");
        Console.WriteLine("  Error: {0}", e.Error.Message);
        // You can inspect e.Error for more details about the exception.
        // Consider logging the error and potentially closing the stream.
        if (sender is SslStream sslStream) {
            // sslStream.Close(); // Might be appropriate depending on the error
        }
    }

    // To run this example, you would call ConnectAndAuthenticateAsync from your application's entry point.
    // Example:
    // static async Task Main(string[] args) {
    //     await ConnectAndAuthenticateAsync("example.com", 443);
    // }
    
}
            

See Also

SslStream | SSLStreamAsyncErrorEventArgs | System.Net.Security Namespace