Sylwester Lachiewicz created THRIFT-6233:
--------------------------------------------

             Summary: Make the peer-address check on TSSLServerSocket opt-in
                 Key: THRIFT-6233
                 URL: https://issues.apache.org/jira/browse/THRIFT-6233
             Project: Thrift
          Issue Type: Improvement
          Components: Python - Library
            Reporter: Sylwester Lachiewicz
             Fix For: 0.25.0


{{TSSLServerSocket}} calls its default {{validate_callback}} with the client 
certificate and the address the connection arrived from, and on Python 3.12 and 
later that default ({{sslcompat.match_peer_ipaddress}}) accepts the certificate 
only when the address appears among its IP subjectAltName records. Python is 
the only binding that does this by default: the C++ and D access managers are 
installed on client sockets only, and the other bindings with a TLS server 
leave client-certificate policy to the TLS configuration or to a callback the 
application supplies.

A client checks the server's certificate against the name it meant to reach. A 
server has no such reference for its clients: the source address is not 
something the client asserts, and NAT, proxies, load balancers and container 
networking rewrite it routinely, so a client certificate often cannot carry the 
address the server will see. Which certificates may connect is the 
application's policy, expressed through a {{validate_callback}} that looks at 
the subject or the subjectAltName, or through a CA that issues only to the 
clients meant to connect. THRIFT-3599 added the check in 0.10.0 so that a 
server would not accept just any certificate its CA had signed; the peer 
address is a poor stand-in for that. It only concerns servers that request 
client certificates, since {{cert_reqs}} defaults to {{CERT_NONE}}. As master 
stands, 0.25.0 would start refusing clients on Python 3.12 and later whose 
certificates do not list the address the server sees.

Change:
* {{TSSLServerSocket}} defaults {{validate_callback}} to {{None}}. OpenSSL 
still verifies the client certificate against {{ca_certs}} whenever 
{{cert_reqs}} asks for one.
* {{thrift.transport.sslcompat.match_peer_ipaddress}} stays as the documented 
way to opt back in: {{validate_callback=match_peer_ipaddress}}.
* {{TSSLSocket}} and {{sslcompat._match_hostname}} are unchanged; the client 
path still relies on them.
* The {{_match_has_ipaddress}} check that raised {{ValueError}} in 
{{TSSLServerSocket.__init__}} goes, since it only made sense while the matcher 
was the default.
* 
[lib/py/README.md|https://github.com/apache/thrift/blob/master/lib/py/README.md]
 (Breaking Changes, 0.25.0) and 
[test/keys/README.md|https://github.com/apache/thrift/blob/master/test/keys/README.md]
 are updated, with a note for servers on Python 3.11 or earlier that relied on 
the check: the opt-in covers addresses listed as IP subjectAltName records, not 
the commonName fallback that {{ssl.match_hostname}} also applied.
* Tests go through {{TSSLServerSocket.accept()}}: {{client.crt}}, trusted by 
the server but carrying no IP subjectAltName, is accepted by default and 
refused with the opt-in; {{client_v3.crt}} is accepted with it.

Follow-up agreed on [PR #3818|https://github.com/apache/thrift/pull/3818], 
which keeps the opt-in matcher treating {{::ffff:127.0.0.1}} and {{127.0.0.1}} 
as the same address 
([THRIFT-6201|https://issues.apache.org/jira/browse/THRIFT-6201]).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to