[Python-Dev] Simplify and unify SSL verification
Christian Heimes
christian at python.org
Thu Nov 7 22:42:30 CET 2013
Am 07.11.2013 21:45, schrieb Antoine Pitrou:
> I'm in favour but I think 3.5 is too early. Keep in mind SSLContext is
> quite young.
It's available since 3.3
>> - deprecate implicit verify_mode=CERT_NONE. Python 3.5 will default
>> to CERT_REQUIRED.
>
> -0.9. This breaks compatibility and doesn't achieve anything, since
> there's no reliable story for CA certs.
I'd like to move to "secure by default". The CA cert situation is solved
on most platforms.
> Service matching is an application protocol level thing, it isn't
> strictly part of SSL. I'd feel warmer if you removed the "by default" part.
Hostname matching is done through an explicit call to
SSLSocket.check_cert(). All Python stdlib libraries like smtplib, ftplib
etc. are going to verify the hostname by default. 3rd party libraries
have to call check_cert() explicitly.
>> - add ssl.get_default_context() to acquire a default SSLContext object
>> if the context argument is None. (Python 3.4)
>
> I think I'm against it, for two reasons:
>
> 1. It will in the long term create compatibility and/or security issues
> (we'll have to keep fragile legacy settings if we want to avoid breaking
> existing uses of the default context)
>
> 2. SSLContexts are mutable, which means some code can affect other
> code's behaviour without even knowing. It's a recipe for subtle bugs and
> security issues.
>
> Applications and/or higher-level libraries should be smart enough to
> choose their own security preferences, and it's the better place to do
> so anyway.
You misunderstood me. I'm not proposing a global SSLContext object but a
factory function that creates a context for Python stdlib modules. Right
now every urllib, http.client, nntplib, asyncio, ftplib, poplib and
imaplib have duplicated code. I'd like to have ONE function that creates
and configures a SSLContext object with sensible default values for
Python stdlib.
3rd party apps are free to create their own SSLContext object.
> The check_cert() function wouldn't achieve anything besides calling
> match_hostname(), right?
It does more: http://pastebin.com/gKi7N2WM
> I'm against calling it check_cert(), it's too generic and only induces
> confusion.
Do you have an idea for a better name?
>
>> The SSLContext's check_cert option will support four values:
>>
>> None (default)
>> use match_hostname() if verify_mode is CERT_OPTIONAL or
>> CERT_REQUIRED
>> True
>> always use match_hostname()
>> False
>> never use match_hostname()
>
> What is the hostname that the cert is matched against?
The library code must provide as argument to check_cert or it's taken
from server_hostname if no hostname is provided.
> And why is there an "initiator" object? Personally I prefer to avoid
> passing opaque user data, since the caller can use a closure anyway.
> And what are the **kwargs?
No, they can't use a closure. The callback function is part of the
SSLContext object. The context object can be used by multiple SSLSocket
objects. The **kwargs make it possible to pass data from the caller of
check_cert() to the callback function of the SSLContext instance.
> So what does this bring compared to the statu quo? I thought at least
> sock.check_cert() would be called automatically, but if you have to call
> it yourself it starts looking pointless, IMO.
As you have said earlier, cert matching is not strictly a SSL connection
thing. With the check_cert feature you can do stuff like validation of
self-signed certs with known hash sums:
def check_cert_cb(sslsock, hostname, initiator, **kwargs):
# real code would use SPKI
certdigest = sha1(sslsock.getpeercert(True)).digest()
if hostname == "my.host.name" and certdigest == b"abcdef...":
return True
do_other_check(sslsock, hostname)
ctx = SSLContext(PROTOCOL_TLSv1, check_cert_cb)
ctx.verify_mode = CERT_NONE
httpscon = http.client.HTTPSConnection("my.host.name", 443, context=ctx)
httpscon = http.client.HTTPSConnection("my.host.name", 443, context=ctx)
httpscon = http.client.HTTPSConnection("my.host.name", 443, context=ctx)
Christian
More information about the Python-Dev
mailing list