glyph / txsni

Simple support for running a TLS server with Twisted.
MIT License
25 stars 10 forks source link

support Deferreds from the SNI map #17

Open glyph opened 7 years ago

glyph commented 7 years ago

It should be possible to support a Deferred returned from SNIMap's mapping parameter, allowing for certificates to be requested from a remote certificate store, such as a back-end database, rather than the filesystem.

Right now, SNIMap requires the synchronous construction of a Context object, so we must synchronously construct one. Superficially, the structure of TLS support requires this.

However.

We already construct a _ConnectionProxy rather than handing a Connection directly back to Twisted. All the bytes received from the connection go to this object, not the underlying Connection, via bio_write. We can create a throw-away Connection object that we pass bytes to, waiting for the SNI hook, and then instead of assigning its Context and letting it continue the connection, instead we fire off a Deferred.

When that Deferred fires, we need to feed those same handshake bytes into a new Connection object, this one with the correct Context already set; the one extra trick is that we need to somehow have a reference to the TLSMemoryBIOProtocol to call _flushSendBIO on it, now that we can send out the now-available ServerHello that we have available, given our SNI-selected backend certificate. Luckily, we got that passed in to us with serverConnectionForTLS! Technically speaking we can do this all with public APIs, just using proto.transport.write(self._obj.bio_read()) to kick off the next write.

mithrandi commented 7 years ago

I think perhaps a different API shape might be appropriate if we implement this; while there's nothing technically preventing you from having mapping[key] → Deferred, having __special__ methods returning Deferreds is not exactly idiomatic and will probably be highly surprising.

Also, whatever interface we end up with here should be compatible with ICertificateStore from txacme one way or the other (probably by making the interface the same in both places, but providing an adapter might also be okay).