Represents the method that handles validation of an SSL certificate.
public delegate bool SslValidationCallback(
object sender,
string targetHost,
X509Certificate2 certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors
);
| 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. |
| Type | Description |
|---|---|
bool |
true if the certificate is trusted; otherwise, false. |
|
The When you create an instance of The callback method you provide should examine the provided parameters, especially Important: In production environments, it is generally recommended to perform thorough certificate validation to ensure the security of your application. Relying solely on returning |
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);
// }
}
Namespace: System.Net.Security
Assembly: System.Net.Primitives.dll (in .NET Core and .NET 5+)
Assembly: System.dll (in .NET Framework)