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