homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Errno conflicts in ssl.SSLError
Type: behavior Stage: needs patch
Components: SSL Versions: Python 3.7, Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Ben.Darnell, alex, christian.heimes, dstufft, janssen, martin.panter, nagle, pitrou
Priority: normal Keywords:

Created on 2015年03月05日 04:10 by Ben.Darnell, last changed 2022年04月11日 14:58 by admin.

Messages (7)
msg237239 - (view) Author: Ben Darnell (Ben.Darnell) * Date: 2015年03月05日 04:10
ssl.SSLError is a subclass of OSError but uses error codes that come from a different scope than the standard errno constants and may have conflicts. For example, on my system (OSX), ssl.SSL_ERROR_WANT_X509_LOOKUP and errno.EINTR have the same value. This would cause problems for code like the following:
 def f():
 while True:
 try:
 return ssl_sock.read()
 except OSError as e:
 if e.errno == errno.EINTR:
 continue
 raise
This function would loop endlessly on ssl.SSL_ERROR_WANT_X509_LOOKUP. (Note that I have not run into any problem like this in practice so this is not a severe issue; I just stumbled across the possibility). The EINTR case is moot now that Python itself retries on EINTR, but other conflicts are possible (the problem is also mitigated by the fact that most of the interesting errnos now have dedicated exception subtypes)
To use OSError.errno correctly, it is currently necessary to check the exact type of the exception; it is not enough to do subclass matching as is usual for exceptions. To remedy this, I propose either changing the numeric constants in the SSL module (if these are not required to match constants defined in openssl), or adding an attribute to OSError like 'errno_scope' to be used when interpreting the errno field.
msg237487 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015年03月08日 00:55
[padding]
This behaviour of returning an SSL-specific error code in the "errno" attribute is not documented. The "errno" attribute is actually specified to hold a POSIX error code, and I don’t think this specification should be changed.
I don’t see how checking for an "errno_scope" attribute is any better than checking for isinstance(exception, SSLError). I think the SSL error codes should be removed from "errno", or maybe moved to a new attribute (ssl_error?), like what is already done with the "winerror" attribute.
msg237508 - (view) Author: Ben Darnell (Ben.Darnell) * Date: 2015年03月08日 03:17
I agree that SSLError should have used a different attribute, but it's too late for that - changing it would break any code currently relying on SSL errnos (in particular asynchronous code using the SSL_ERROR_WANT_{READ,WRITE} error codes for normal operation).
errno_scope is better than checking for isinstance(SSLError) because it lets code that only wants posix errno to say so, instead of having to know about and blacklist every OSError subclass that abuses the errno attribute (is SSLError the only one?)
msg237512 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015年03月08日 06:24
Okay I see your point about backwards compatibility now. Indeed, I have written code myself before Python 3.3 that used to inspect err.args[0], and it would suffer a similar problem if I had not updated it to use the new Python 3.3 exception subclasses.
Below I have written a comparison of two options that have been proposed. Both have disadvantages and would potentially require changes in user code.
A third middle-ground option might be to deprecate OSError.errno as well, and replace it with OSError.posix_errno or something. But I would still prefer the option to stop setting SSLError.errno, even though it breaks backwards compatibility. I think we can at least agree that "errno" and "args" should be deprecated for SSLError instances.
## Option 1: Add OSError.errno_scope ##
To avoid the bug in new Python versions we would still have to modify code handling a general OSError (EnvironmentError), for example:
# Buggy handler compatible with Python 3.2
try:
 return ssl_sock.read()
except EnvironmentError as e:
 if e.errno != errno.EINTR:
 raise
# Fixed handler, supporting new Python versions only
try:
 return ssl_sock.read()
except OSError as e:
 if e.errno_scope != POSIX or e.errno != errno.EINTR:
 raise
Advantages:
* Existing code still works if you don’t care about this bug
* No code changes required in SSL error handlers
## Option 2: Stop setting SSLError.errno ##
Existing SSLError handlers written for Python < 3.3 would stop catching exceptions, because "errno" defaults to None. This would probably cause an unhandled exception, and could be fixed as follows:
# Broken handler written for Python 3.2
try:
 return ssl_sock.read()
except SSLError as e:
 if e.errno != SSL_ERROR_WANT_READ:
 raise
 # Handle non-blocking read
# Fixed handler, supporting Python 3.3+ only
try:
 return ssl_sock.read()
except SSLWantReadError as e:
 # Handle non-blocking read
Advantages:
* Affected code should be easy to find due to breakage
* Only requires the user to change code that directly handles SSL errors
* No changes for code already written for Python 3.3
* Code changes only when relying on the undocumented errno behaviour, which is already asking for trouble
msg237513 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015年03月08日 06:44
Sorry I take back my claim that the error codes were undocumented; see the example code in <https://docs.python.org/3.2/library/ssl.html#ssl-nonblocking>.
Perhaps the most compatible way to fix this would be to change the SSL error codes to something (custom class?) that does not compare equal to any possible POSIX error code.
msg237555 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2015年03月08日 19:33
Theoretically, SSLError could stop inheriting from OSError. Practically, it may break a lot of code (though in a rather noisy way that is easy to spot).
Otherwise, the best effort fix is to make our SSL error codes start at a high number, e.g. 2000 (but not too high, so as not to overlap with Windows' socket error codes, which start at 10000 IIRC). See the "py_ssl_error" enum at the beginning of _ssl.c.
msg239837 - (view) Author: John Nagle (nagle) Date: 2015年04月01日 19:19
If SSL error reporting is getting some attention, something should be done to provide better text messages for the SSL errors. All certificate verify exceptions return the string "certificate verify failed (_ssl.c:581)". The line number in _ssl.c is not particularly useful to end users. OpenSSL has more specific messages, but they're not making it to the Python level.
'python ssl "certificate verify failed"' has 17,000 hits in Google, which indicates users need more help dealing with this class of error.
History
Date User Action Args
2022年04月11日 14:58:13adminsetgithub: 67776
2017年09月07日 20:51:14christian.heimessetassignee: christian.heimes ->
2016年09月15日 07:54:25christian.heimessetassignee: christian.heimes
components: + SSL
2016年09月08日 15:22:32giampaolo.rodolasetnosy: - giampaolo.rodola
2016年09月08日 15:19:51christian.heimessetversions: + Python 3.6, Python 3.7, - Python 3.4, Python 3.5
2015年04月01日 19:19:19naglesetnosy: + nagle
messages: + msg239837
2015年03月08日 19:33:02pitrousetmessages: + msg237555
stage: needs patch
2015年03月08日 06:44:12martin.pantersetmessages: + msg237513
2015年03月08日 06:24:40martin.pantersetmessages: + msg237512
2015年03月08日 03:17:34Ben.Darnellsetmessages: + msg237508
2015年03月08日 00:55:30martin.pantersetnosy: + martin.panter
messages: + msg237487
2015年03月05日 05:37:32ned.deilysetnosy: + janssen, pitrou, giampaolo.rodola, christian.heimes, alex, dstufft

versions: + Python 3.4, Python 3.5
2015年03月05日 04:10:08Ben.Darnellcreate

AltStyle によって変換されたページ (->オリジナル) /