<div dir="ltr">I'm going to leave the design up to Nick and friends for a while. Let me know when there is a patch to review.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 9, 2014 at 3:52 AM, Nick Coghlan <span dir="ltr"><<a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 9 September 2014 03:44, Alex Gaynor <<a href="mailto:alex.gaynor@gmail.com">alex.gaynor@gmail.com</a>> wrote:<br>
> *Shifts uncomfortably* it looks like presently there's not a good way to<br>
> change anything about the SSL configuration for urllib.request.urlopen. It<br>
> does not take a `context` argument, as the http.client API does:<br>
> <a href="https://docs.python.org/3/library/urllib.request.html#module-urllib.request" target="_blank">https://docs.python.org/3/library/urllib.request.html#module-urllib.request</a><br>
> and instead takes the cafile, capath, cadefault args.<br>
><br>
> This would need to be updated first, once it *did* take such an argument,<br>
> this would be accomplished by:<br>
><br>
> context = ssl.create_default_context()<br>
> context.verify_mode = CERT_OPTIONACERT_NONE<br>
> context.verify_hostname = False<br>
> urllib.request.urlopen("<a href="https://something-i-apparently-dont-care-much-about" target="_blank">https://something-i-apparently-dont-care-much-about</a>",<br>
> context=context)<br>
<br>
I'd never needed to use the existing global configuration settings in<br>
urllib.request before, but it actually *does* already support setting<br>
the default opener for urllib.urlopen.<br>
<br>
To explicitly set it to use verified HTTPS by default:<br>
<br>
    import ssl, urllib.request<br>
    https_handler = HTTPSHandler(context=ssl.create_default_context(),<br>
check_hostname=True)<br>
    urllib.request.install_opener(urllib.request.build_opener(https_handler)<br>
<br>
When the default changes, turning off verification by default for<br>
urllib.request.urlopen would look like:<br>
<br>
    import ssl, urllib.request<br>
    unverified_context = ssl.create_default_context()<br>
    unverified_context.verify_mode = CERT_OPTIONACERT_NONE<br>
    unverified_context.verify_hostname = False<br>
    unverified_handler = HTTPSHandler(context=unverified_context,<br>
check_hostname=False)<br>
    urllib.request.install_opener(urllib.request.build_opener(unverified_handler)<br>
<br>
However, even setting the opener like that still leaves<br>
http.client.HTTPSConnection, urllib.request.URLOpener and<br>
urllib.request.FancyURLOpener using unverified HTTPS with no easy way<br>
to change their default behaviour.<br>
<br>
That means some other approach to global configuration is going to be<br>
needed to cover the "coping with legacy corporate infrastructure"<br>
case, and I still think a monkeypatching based hack is likely to be<br>
our best bet.<br>
<br>
So, focusing on 3.4, but in a way that should be feasible to backport,<br>
the changes that I now believe would be needed are:<br>
<br>
1. Add "context" arguments to urlopen, URLOpener and FancyURLOpener<br>
(the latter two have been deprecated since 3.3, but this would make<br>
things easier for a subsequent 2.7 backport)<br>
2. Add a ssl._create_https_context() alias for ssl.create_default_context()<br>
3. Change urllib.request.urlopen() and http.client.HTTPSConnection to<br>
call ssl_create_https_context() rather than<br>
ssl._create_stdlib_context()<br>
4. Rename ssl._create_stdlib_context() to<br>
ssl._create_unverified_context() (updating call sites accordingly)<br>
<br>
To revert any given call site to the old behaviour:<br>
<br>
    http.client.HTTPSConnection(context=ssl._create_unverified_context())<br>
    urllib.request.urlopen(context=ssl._create_unverified_context())<br>
    urllib.request.URLOpener(context=ssl._create_unverified_context())<br>
    urllib.request.FancyURLOpener(context=ssl._create_unverified_context())<br>
<br>
And to revert to the old default behaviour globally:<br>
<br>
    import ssl<br>
    ssl._create_https_context = ssl._create_unverified_context<br>
<br>
The backport to 2.7 would then be a matter of bringing urllib,<br>
urllib2, httplib and ssl into line with their 3.4.2 counterparts.<br>
<br>
Regards,<br>
Nick.<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>   |   Brisbane, Australia<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>--Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)
</div>