| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
There was a problem hiding this comment.
"labe"
Sorry, something went wrong.
There was a problem hiding this comment.
(also not sure what the deal with github rendering all this with underlines is; potential reST issue?)
Sorry, something went wrong.
There was a problem hiding this comment.
It's caused by a supernumerous backtick. I have fixed both issues.
Sorry, something went wrong.
There was a problem hiding this comment.
Unrelated?
Sorry, something went wrong.
There was a problem hiding this comment.
Remnants of debugging failing tests
Sorry, something went wrong.
|
I did a quick skim and the code seems fine to me, but... I do think that for set_servername_callback, instead of just breaking things we maybe we need to rename it and add a compatibility shim. Quoting from https://mail.python.org/pipermail/python-dev/2017-December/151527.html:
|
Sorry, something went wrong.
|
Meh! :( Let's make it PEP 543 compatible and add sni_callback property. The Python subclass can provide your shim cb. Thanks for proposing it! |
Sorry, something went wrong.
Historically, our handling of international domain names (IDNs) in the
ssl module has been very broken. The flow went like:
1. User passes server_hostname= to the SSLSocket/SSLObject
constructor. This gets normalized to an A-label by using the
PyArg_Parse "et" mode: bytes objects get passed through
unchanged (assumed to already be A-labels); str objects get run
through .encode("idna") to convert them into A-labels.
2. newPySSLSocket takes this A-label, and for some reason decodes
it *back* to a U-label, and stores that as the object's
server_hostname attribute.
3. Later, this U-label server_hostname attribute gets passed to
match_hostname, to compare against the hostname seen in the
certificate. But certificates contain A-labels, and match_hostname
expects to be passed an A-label, so this doesn't work at all.
This PR fixes the problem by removing the pointless decoding at step
2, so that internally we always use A-labels, which matches how
internet protocols are designed in general: A-labels are used
everywhere internally and on-the-wire, and U-labels are basically just
for user interfaces.
This also matches the general advice to handle encoding/decoding once
at the edges, though for backwards-compatibility we continue to use
'str' objects to store A-labels, even though they're now always
ASCII. Technically there is a minor compatibility break here: if a
user examines the .server_hostname attribute of an ssl-wrapped socket,
then previously they would have seen a U-label like "pythön.org", and
now they'll see an A-label like "xn--pythn-mua.org". But this only
affects non-ASCII domain names, which have never worked in the first
place, so it seems unlikely that anyone is relying on the old
behavior.
This PR also adds an end-to-end test for IDN hostname
validation. Previously there were no tests for this functionality.
Fixes bpo-28414.
All test certs must be generated by CPython's own test helper. Signed-off-by: Christian Heimes <christian@python.org>
Signed-off-by: Christian Heimes <christian@python.org>
There was a problem hiding this comment.
I pushed some prose changes, and here are some comments on the code. Overall looks good, but there are a few small cleanups to consider, and a few points where I have questions.
Sorry, something went wrong.
| self.sni_callback = None | ||
| else: | ||
| if not hasattr(server_name_callback, '__call__'): | ||
| raise TypeError("not a callable object") |
There was a problem hiding this comment.
Why not if not callable(server_name_callback)?
Sorry, something went wrong.
There was a problem hiding this comment.
Ah right, callable was re-added in Python 3.2. I'll change it.
Sorry, something went wrong.
|
|
||
| def shim_cb(sslobj, servername, sslctx): | ||
| if servername is not None: | ||
| servername = servername.encode("ascii").decode("idna") |
There was a problem hiding this comment.
It would be simpler to use _encode_hostname here, no?
Sorry, something went wrong.
There was a problem hiding this comment.
I don't mind to use the method here, too.
Sorry, something went wrong.
|
|
||
| def __init__(self, protocol=PROTOCOL_TLS): | ||
| self.protocol = protocol | ||
| def _encode_hostname(self, hostname): |
There was a problem hiding this comment.
Maybe make this a top-level utility function, instead of a method?
Sorry, something went wrong.
There was a problem hiding this comment.
I'd prefer to keep this a method. It makes it easier to modify the behavior in subclasses or in tests.
Sorry, something went wrong.
| {"options", (getter) get_options, | ||
| (setter) set_options, NULL}, | ||
| {"protocol", (getter) get_protocol, | ||
| NULL, NULL}, |
There was a problem hiding this comment.
Why is this new protocol attribute in this PR? Should it be documented or anything?
Sorry, something went wrong.
There was a problem hiding this comment.
It's not new: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.protocol
I just moved it from Python code into C code so I can access the value from C methods. The new setter for the callback uses the value to prevent setting a SNI callback for a client-only context.
Sorry, something went wrong.
There was a problem hiding this comment.
Ah, gotcha.
Sorry, something went wrong.
| Py_INCREF(result); | ||
| Py_SETREF(ssl->ctx, (PySSLContext *)result); | ||
| SSL_set_SSL_CTX(ssl->ssl, ssl->ctx->ctx); | ||
| } |
There was a problem hiding this comment.
The docs just say that sni_callback has to return None. What's this extra context setting stuff about? Should it be removed?
Sorry, something went wrong.
There was a problem hiding this comment.
I added the code for future compatibility with PEP 543. Rather than modifying socket.context, the callback can return a new context and let the API take care of the rest.
By the way it doesn't have to be None. Other values signal an error:
The server_name_callback function must return None to allow the TLS negotiation to continue. If a TLS failure is required, a constant ALERT_DESCRIPTION_* can be returned. Other return values will result in a TLS fatal error with ALERT_DESCRIPTION_INTERNAL_ERROR.
Sorry, something went wrong.
There was a problem hiding this comment.
Ok yeah, I think adding new undocumented features in b2 for partial compatibility with an unfinished PEP is probably a bad plan, so thanks for removing that :-). It'll be easy to add back later.
Sorry, something went wrong.
Drop extra code for PEP 543 future compatibility in sni callback Use callable() and encode_hostname in shim for old SNI callback. Signed-off-by: Christian Heimes <christian@python.org>
|
The context special handling is pining for the fjords. |
Sorry, something went wrong.
) Previously, the ssl module stored international domain names (IDNs) as U-labels. This is problematic for a number of reasons -- for example, it made it impossible for users to use a different version of IDNA than the one built into Python. After this change, we always convert to A-labels as soon as possible, and use them for all internal processing. In particular, server_hostname attribute is now an A-label, and on the server side there's a new sni_callback that receives the SNI servername as an A-label rather than a U-label. (cherry picked from commit 11a1493) Co-authored-by: Christian Heimes <christian@python.org>
|
GH-5843 is a backport of this pull request to the 3.7 branch. |
Sorry, something went wrong.
…H-5843) Previously, the ssl module stored international domain names (IDNs) as U-labels. This is problematic for a number of reasons -- for example, it made it impossible for users to use a different version of IDNA than the one built into Python. After this change, we always convert to A-labels as soon as possible, and use them for all internal processing. In particular, server_hostname attribute is now an A-label, and on the server side there's a new sni_callback that receives the SNI servername as an A-label rather than a U-label. (cherry picked from commit 11a1493) Co-authored-by: Christian Heimes <christian@python.org>
|
Why are there no tests for the new function name, the tests in the stdlib all refer to set_servername_callback ? |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Alternative approach to PR #3010
https://bugs.python.org/issue28414