[Python-Dev] Simplify and unify SSL verification (original) (raw)
Christian Heimes christian at python.org
Thu Nov 7 22:42:30 CET 2013
- Previous message: [Python-Dev] Simplify and unify SSL verification
- Next message: [Python-Dev] Simplify and unify SSL verification
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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 verifymode=CERTNONE. Python 3.5 will default to CERTREQUIRED. -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.getdefaultcontext() 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 checkcert() function wouldn't achieve anything besides calling matchhostname(), right?
It does more: http://pastebin.com/gKi7N2WM
I'm against calling it checkcert(), it's too generic and only induces confusion.
Do you have an idea for a better name?
The SSLContext's checkcert option will support four values:
None (default) use matchhostname() if verifymode is CERTOPTIONAL or CERTREQUIRED True always use matchhostname() False never use matchhostname() 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.checkcert() 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
- Previous message: [Python-Dev] Simplify and unify SSL verification
- Next message: [Python-Dev] Simplify and unify SSL verification
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]