Export (0) Print
Expand All

SslStream Class

Provides a stream used for client-server communication that uses the Secure Socket Layer (SSL) security protocol to authenticate the server and optionally the client.

Namespace:  System.Net.Security
Assembly:  System (in System.dll)

'Declaration
Public Class SslStream _
	Inherits AuthenticatedStream
'Usage
Dim instance As SslStream

SSL protocols help to provide confidentiality and integrity checking for messages transmitted using an SslStream. An SSL connection, such as that provided by SslStream, should be used when communicating sensitive information between a client and a server. Using an SslStream helps to prevent anyone from reading and tampering with information while it is in transit on the network.

An SslStream instance transmits data using a stream that you supply when creating the SslStream. When you supply this underlying stream, you have the option to specify whether closing the SslStream also closes the underlying stream. Typically, the SslStream class is used with the TcpClient and TcpListener classes. The GetStream method provides a NetworkStream suitable for use with the SslStream class.

After creating an SslStream, the server and optionally, the client must be authenticated. The server must provide an X509 certificate that establishes proof of its identity and can request that the client also do so. Authentication must be performed before transmitting information using an SslStream. Clients initiate authentication using the synchronous AuthenticateAsClient methods, which block until the authentication completes, or the asynchronous BeginAuthenticateAsClient methods, which do not block waiting for the authentication to complete. Servers initiate authentication using the synchronous AuthenticateAsServer or asynchronous BeginAuthenticateAsServer methods. Both client and server must initiate the authentication.

The authentication is handled by the Security Support Provider (SSPI) channel provider. The client is given an opportunity to control validation of the server's certificate by specifying a RemoteCertificateValidationCallback delegate when creating an SslStream. The server can also control validation by supplying a RemoteCertificateValidationCallback delegate. The method referenced by the delegate includes the remote party's certificate and any errors SSPI encountered while validating the certificate. Note that if the server specifies a delegate, the delegate's method is invoked regardless of whether the server requested client authentication. If the server did not request client authentication, the server's delegate method receives a null certificate and an empty array of certificate errors.

If the server requires client authentication, the client must specify one or more certificates for authentication. If the client has more than one certificate, the client can provide a LocalCertificateSelectionCallback delegate to select the correct certificate for the server. The client's certificates must be located in the current user's "My" certificate store. Client authentication via certificates is not supported for the Ssl2 (SSL version 2) protocol.

If the authentication fails, you receive a AuthenticationException, and the SslStream is no longer useable. You should close this object and remove all references to it so that it can be collected by the garbage collector.

When the authentication process, also known as the SSL handshake, succeeds, the identity of the server (and optionally, the client) is established and the SslStream can be used by the client and server to exchange messages. Before sending or receiving information, the client and server should check the security services and levels provided by the SslStream to determine whether the protocol, algorithms, and strengths selected meet their requirements for integrity and confidentiality. If the current settings are not sufficient, the stream should be closed. You can check the security services provided by the SslStream using the IsEncrypted and IsSigned properties. The following table shows the elements that report the cryptographic settings used for authentication, encryption and data signing.

Element

Members

The security protocol used to authenticate the server and, optionally, the client.

The SslProtocol property and the associated SslProtocols enumeration.

The key exchange algorithm.

The KeyExchangeAlgorithm property and the associated ExchangeAlgorithmType enumeration.

The message integrity algorithm.

The HashAlgorithm property and the associated HashAlgorithmType enumeration.

The message confidentiality algorithm.

The CipherAlgorithm property and the associated CipherAlgorithmType enumeration.

The strengths of the selected algorithms.

The KeyExchangeStrength, HashStrength, and CipherStrength properties.

After a successful authentication, you can send data using the synchronous Write or asynchronous BeginWrite methods. You can receive data using the synchronous Read or asynchronous BeginRead methods.

If you specified to the SslStream that the underlying stream should be left open, you are responsible for closing that stream when you are done using it.

NoteNote:

If the application that creates the SSLStream object runs with the credentials of a Normal user, the application will not be able to access certificates installed in the local machine store unless permission has been explicitly given to the user to do so.

The following code example demonstrates creating an TcpListener that uses the SslStream class to communicate with clients.

No code example is currently available or this language may not be supported.
#using <mscorlib.dll>
#using <System.dll>
using namespace System;
using namespace System::Collections;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Net::Security;
using namespace System::Security::Authentication;
using namespace System::Text;
using namespace System::Security::Cryptography::X509Certificates;
using namespace System::IO;

public __sealed __gc class SslTcpServer 
{
    static X509Certificate* serverCertificate = 0;
    // The certificate parameter specifies the name of the file 
    // containing the machine certificate.
public:
    static void RunServer(String* certificate) 
    {
        serverCertificate = X509Certificate::CreateFromCertFile(certificate);
        // Create a TCP/IP (IPv4) socket and listen for incoming connections.
        TcpListener* listener = new TcpListener(IPAddress::Any, 8080);    
        listener->Start();
        while (true) 
        {
            Console::WriteLine(S"Waiting for a client to connect...");
            // Application blocks while waiting for an incoming connection.
            // Type CNTL-C to terminate the server.
            TcpClient* client = listener->AcceptTcpClient();
            ProcessClient(client);
        }
    }
    static void ProcessClient (TcpClient* client)
    {
        // A client has connected. Create the 
        // SslStream using the client's network stream.
        SslStream* sslStream = new SslStream(
            client->GetStream(), false);
        // Authenticate the server but don't require the client to authenticate.
        try 
        {
            sslStream->ServerAuthenticate(serverCertificate, 
                false, SslProtocolType::Tls, true);
            // Display the properties and settings for the authenticated stream.
            DisplaySecurityLevel(sslStream);
            DisplaySecurityServices(sslStream);
            DisplayCertificateInformation(sslStream);
            DisplayStreamProperties(sslStream);

            // Set timeouts for the read and write to 5 seconds.
            sslStream->ReadTimeout = 5000;
            sslStream->WriteTimeout = 5000;
            // Read a message from the client.   
            Console::WriteLine(S"Waiting for client message...");
            String* messageData = ReadMessage(sslStream);
            Console::WriteLine(S"Received: {0}", messageData);

            // Write a message to the client.
            Byte message[] = Encoding::UTF8->GetBytes(S"Hello from the server.<EOF>");
            Console::WriteLine(S"Sending hello message.");
            sslStream->Write(message);
        }
        catch (AuthenticationException* e)
        {
            Console::WriteLine(S"Exception: {0}", e->Message);
            if (e->InnerException != 0)
            {
                Console::WriteLine(S"Inner exception: {0}", e->InnerException->Message);
            }
            Console::WriteLine (S"Authentication failed - closing the connection.");
            sslStream->Close();
            client->Close();
            return;
        }
        __finally
        {
            // The client stream will be closed with the sslStream
            // because we specified this behavior when creating
            // the sslStream.
            sslStream->Close();
            client->Close();
        }
    }
    static String* ReadMessage(SslStream* sslStream)
    {
        // Read the  message sent by the client.
        // The client signals the end of the message using the
        // "<EOF>" marker.
        Byte buffer[] = new Byte[2048];
        StringBuilder* messageData = new StringBuilder();
        int bytes = -1;
        do
        {
            // Read the client's test message.
            bytes = sslStream->Read(buffer, 0, buffer->Length);

            // Use Decoder class to convert from bytes to UTF8
            // in case a character spans two buffers.
            Decoder* decoder = Encoding::UTF8->GetDecoder();
            Char chars[] = new Char[decoder->GetCharCount(buffer,0,bytes)];
            decoder->GetChars(buffer, 0, bytes, chars,0);
            messageData->Append (chars);
            // Check for EOF or an empty message.
            if (messageData->ToString()->IndexOf(S"<EOF>") != -1)
            {
                break;
            }
        } while (bytes !=0); 

        return messageData->ToString();
    }
    static void DisplaySecurityLevel(SslStream* stream)
    {
        Console::WriteLine(S"Cipher: {0} strength {1}", __box(stream->CipherAlgorithm), __box(stream->CipherStrength));
        Console::WriteLine(S"Hash: {0} strength {1}", __box(stream->HashAlgorithm), __box(stream->HashStrength));
        Console::WriteLine(S"Key exchange: {0} strength {1}", __box(stream->KeyExchangeAlgorithm), __box(stream->KeyExchangeStrength));
        Console::WriteLine(S"Protocol: {0}", __box(stream->SslProtocol));
    }
    static void DisplaySecurityServices(SslStream* stream)
    {
        Console::WriteLine(S"Is authenticated: {0} as server? {1}", __box(stream->IsAuthenticated), __box(stream->IsServer));
        Console::WriteLine(S"IsSigned: {0}", __box(stream->IsSigned));
        Console::WriteLine(S"Is Encrypted: {0}", __box(stream->IsEncrypted));
    }
    static void DisplayStreamProperties(SslStream* stream)
    {
        Console::WriteLine(S"Can read: {0}, write {1}", __box(stream->CanRead), __box(stream->CanWrite));
        Console::WriteLine(S"Can timeout: {0}", __box(stream->CanTimeout));
    }
    static void DisplayCertificateInformation(SslStream* stream)
    {
        Console::WriteLine(S"Certificate revocation list checked: {0}", __box(stream->CheckCertRevocationStatus));

        X509Certificate* localCertificate = stream->LocalCertificate;
        if (stream->LocalCertificate != 0)
        {
            Console::WriteLine(S"Local cert was issued to {0} and is valid from {1} until {2}.",
                localCertificate->GetName(),
                localCertificate->GetEffectiveDateString(),
                localCertificate->GetExpirationDateString());
        } else
        {
            Console::WriteLine(S"Local certificate is null.");
        }
        // Display the properties of the client's certificate.
        X509Certificate* remoteCertificate = stream->RemoteCertificate;
        if (stream->RemoteCertificate != 0)
        {
            Console::WriteLine(S"Remote cert was issued to {0} and is valid from {1} until {2}.",
                remoteCertificate->GetName(),
                remoteCertificate->GetEffectiveDateString(),
                remoteCertificate->GetExpirationDateString());
        } else
        {
            Console::WriteLine(S"Remote certificate is null.");
        }
    }
private:
    static void DisplayUsage()
    { 
        Console::WriteLine(S"To start the server specify:");
        Console::WriteLine(S"serverSync certificateFile.cer");
        Environment::Exit(1);
    }
public:
    int RunServerASync()
    {
        String* args[] = Environment::GetCommandLineArgs();

        String* certificate = 0;
        if (args == 0 ||args->Length < 2 )
        {
            DisplayUsage();
        }
        certificate = args[1];
        SslTcpServer::RunServer (certificate);
        return 0;
    } 
};

int main(){
    SslTcpServer* sts = new SslTcpServer();
    sts->RunServerASync();
}

The following code example demonstrates creating a TcpClient that uses the SslStream class to communicate with a server.

No code example is currently available or this language may not be supported.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

.NET Framework

Supported in: 3.5, 3.0, 2.0

Community Additions

ADD
Show:
© 2015 Microsoft