On 2017-01-13 16:58, Cory Benfield wrote:
> 
>> On 13 Jan 2017, at 15:45, Nick Coghlan <ncogh...@gmail.com> wrote:
>>
>> So the essential stack would look like:
>>
>>  TLSConfig[uration?]: implementation independent, settings only
>>  TLSClientContext: ABC to combine settings with a specific TLS implementation
>>  TLSServerContext: ABC to combine settings with a specific TLS implementation
>>  TLSSocket: ABC to combine a context with a network socket
>>  TLSBuffer: ABC to combine a context with a pair of data buffers
>>
>> And then TLSPolicy would be a potential future implementation
>> independent addition that could be used to constrain acceptable TLS
>> configurations.
> 
> If we were going this way, I’d want to add one extra caveat: I think I’d want 
> the Contexts to become immutable.
> 
> The logic for the SNI callback would then become: you are called with the 
> Context that created the socket/buffer, and you return a Configuration object 
> that contains any changes you want to make, and the Context applies them if 
> it can (or errors out if it cannot). A new Context is created. This relegates 
> Context to the role of “socket/buffer factory”. The advantage of this is that 
> we have vastly reduced the moving parts: a Context can ensure that, once 
> initiated, the Policy that belongs to it will not change under its feet. It 
> also allows the Context to refuse to change settings that a given concrete 
> implementation cannot change in the SNI callback.
> 
> Essentially, the logic in the callback would be:
> 
> def sni_callback(buffer, hostname, context):
>     # This creates a writable copy of the configuration: it does not
>     # mutate the original.
>     configuration = context.configuration
>     configuration.certificates = certs_for_hostname(hostname)
>     configuration.inner_protocols = [NextProtocol.H2, NextProtocol.HTTP1]
>     return configuration
> 
> This would almost certainly make Context implementation easier, as there is 
> no longer a requirement to monitor your configuration and support 
> live-updates.

How would this work for OpenSSL? In OpenSSL the SNI callback replaces
the SSL_CTX of a SSL socket pointer with another SSL_CTX. The new
SSL_CTX takes care of cipher negotiation, certs and other handshake
details. The SSL_CTX should be reused in order to benefit from cached
certs, HSM stuff and cached sessions. OpenSSL binds sessions to SSL_CTX
instances.

A callback looks more like this:

contexts = {
    'www.example.org': SSLContext(cert1, key1),
    'internal.example.com': SSLContext(cert2, key2),
}

def sni_callback(sock, hostname):
    sock.context = contexts[hostname]


Christian
_______________________________________________
Security-SIG mailing list
Security-SIG@python.org
https://mail.python.org/mailman/listinfo/security-sig

Reply via email to