-
Notifications
You must be signed in to change notification settings - Fork 139
Description
I've working on an custom httpx transport which uses Kerberos/NTLM/Negotiate authentication when talking to a peer. These authentication methods have a custom extension when talking over TLS called channel binding tokens (CBT) where you embed a structure that is based on information from the TLS context which in essence binds the authentication against the TLS context making it harder to achieve MitM attacks.
A version of CBT that I'm currently using is documented in RFC 5929 which is essentially tls-server-end-point:<cert hash>. In the past I've just send a request to the host, gotten the SSL object from the socket in the response but this has a few problems:
- You waste a round trip sending a request you know will fail
- Somewhat more annoying because in TLS there are more than 1 roundtrips to set up the TLS context
- You need to have set up the connection before you can build the authentication context and generate the first auth token
- If the connection is closed in the auth request then the CBT data you used might not be correct anymore
The last point is problematic because in my scenario I send a blank request which sets up a connection and the response I get back is a 401. Typically I've seen a Connection: close header which has the *ConnectionPool classes drop the connection from the pool. This means the next request is a brand new connection with a brand new negotiated TLS context.
For the tls-server-end-point I could still get the certificate hash as that should be static between the connections but with new protocols like TLS 1.3 the draft proposal for CBT seems to indicate it's based on the unique connection set up Breaking authentication.
What I'm hoping is for is to expose the _open_socket method publically in some shape or form. This would allow me to create the socket connection and set up the TLS request before I send a request through (s)request on the connection. I feel like this could potentially be done by setting up the socket myself and passing it into the __init__() for *HTTPConnection or by just making that method more public by removing the _. This also hinges on my other question around whether connections are actually meant to be publicly exposed in #272.
Very interested to hear your thoughts on this as I do have a working prototype for all this but it relies on being able to access AsyncHTTPConnection and calling _open_socket manually before sending the request through (a)request.