classification
Title: SSLContext.wrap_socket() throws OSError with errno == 0
Type: behavior Stage: patch review
Components: SSL Versions: Python 3.9, Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: christian.heimes Nosy List: Ben.Darnell, Dima.Tisnek, Safihre, christian.heimes, gregory.p.smith, jab, martin.panter, nikratio, remi.lapeyre, shevis, xgdomingo
Priority: normal Keywords: patch

Created on 2017-08-04 19:16 by nikratio, last changed 2020-05-13 00:02 by jab.

Pull Requests
URL Status Linked Edit
PR 18772 open Dima.Tisnek, 2020-03-04 07:25
Messages (12)
msg299759 - (view) Author: Nikolaus Rath (nikratio) * Date: 2017-08-04 19:16
With a particularly atrocious network connection, I often get the following exception:

  File "/usr/lib/python3/dist-packages/dugong/__init__.py", line 503, in connect
    self._sock = self.ssl_context.wrap_socket(self._sock, server_hostname=server_hostname)
  File "/usr/lib/python3.5/ssl.py", line 385, in wrap_socket
    _context=self)
  File "/usr/lib/python3.5/ssl.py", line 760, in __init__
    self.do_handshake()
  File "/usr/lib/python3.5/ssl.py", line 996, in do_handshake
    self._sslobj.do_handshake()
  File "/usr/lib/python3.5/ssl.py", line 641, in do_handshake
    self._sslobj.do_handshake()
OSError: [Errno 0] Error

I don't think an error with errno == 0 should ever be raised by Python.
msg299766 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2017-08-05 01:49
It might help if you explained what “atrocities” are happening on your network. Is there a proxy or man-in-the-middle (or the remote peer) that shuts down TCP connections?

If so, perhaps this is similar to Issue 10808. From my memory, in that case an OS “recv” or “read” call returns zero to indicate a connection was shut down. Python and/or Open SSL correctly treats this as an error, but then assumes “errno” is valid. Perhaps Python should be raising SSLEOFError in this situation.

Maybe also check the “suppress_ragged_eofs” setting, but I think that only affects later stages, after the handshake succeeds.
msg299793 - (view) Author: Nikolaus Rath (nikratio) * Date: 2017-08-05 20:07
Regarding "atrocious connection": I wish I knew, but I have no control of the connection. All I can tell is that there are frequent disconnects, occasional latency spikes, my remote ip address seems to change frequently (while the apparent local one stays as-is, so presumably some NAT in between), temporary bandwidth drops, etc.
msg328093 - (view) Author: Ben Darnell (Ben.Darnell) * Date: 2018-10-20 00:04
We have an easy reproduction of this "[Errno 0] Error" on the server side in https://github.com/tornadoweb/tornado/issues/2504#issuecomment-426782158

It is triggered by a connection from `nc -z` (which I think is doing a TCP handshake and shutting down the connection cleanly, but I'm not sure. It might just send an RST instead of the clean shutdown). On macos, I get SSL_ERROR_EOF (as expected), but on linux it raises an OSError with errno 0. (Note that the script as posted has a small mistake in that it is using a client-side SSLContext on the server side. The same error is seen when that mistake is fixed) 

I'm going to add "errno 0" to the list of errors that Tornado should swallow silently here, so if you're trying to reproduce this in the future use Tornado 5.1.1.
msg332779 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2018-12-31 01:08
This flakiness just caused a PR merge to be blocked by AppVeyor for me:

======================================================================
ERROR: test_with_statement (test.test_nntplib.NetworkedNNTP_SSLTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\projects\cpython\lib\test\test_nntplib.py", line 242, in wrapped
    meth(self)
  File "C:\projects\cpython\lib\test\test_nntplib.py", line 264, in test_with_statement
    with self.NNTP_CLASS(self.NNTP_HOST, timeout=TIMEOUT, usenetrc=False) as server:
  File "C:\projects\cpython\lib\nntplib.py", line 1077, in __init__
    self.sock = _encrypt_on(self.sock, ssl_context, host)
  File "C:\projects\cpython\lib\nntplib.py", line 292, in _encrypt_on
    return context.wrap_socket(sock, server_hostname=hostname)
  File "C:\projects\cpython\lib\ssl.py", line 405, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\projects\cpython\lib\ssl.py", line 853, in _create
    self.do_handshake()
  File "C:\projects\cpython\lib\ssl.py", line 1117, in do_handshake
    self._sslobj.do_handshake()
OSError: [Errno 0] Error
----------------------------------------------------------------------

https://ci.appveyor.com/project/python/cpython/builds/21299396

I lucked out by kicking it with a no-op change to re-trigger an appveyor run where it passed.
msg336732 - (view) Author: Safihre (Safihre) Date: 2019-02-27 07:04
In the CherryPy project it is also observed on Windows with Python 3,7.2.
In CherryPy it's triggered by Checker plugin, which connects to the app listening to the socket port in TLS mode via plain HTTP during startup (from the same process).
It has been around for a while: https://github.com/cherrypy/cherrypy/issues/1618#issuecomment-454150794
msg363318 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-03-04 01:21
I volunteer to test the theory that the connection is closed mid-flight.
msg363322 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-03-04 02:17
Rejoice: https://github.com/dimaqq/bpo-31122
Short, easy to reproduce :)
(I've tested on Mac: 3.7, 3.8, 3.9a from python.org, linked against OpenSSL 1.1.1c/d)
Funnily enough, Python 2.7 raises an ssl.SSLEOFError instead 🤷‍♂️
msg363329 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-03-04 06:50
I've traced it down to here: https://github.com/python/cpython/blob/be501ca2419a91546dea85ef4f36945545458589/Modules/_ssl.c#L791-L798

`err.c` (errno) == 0, no error, and `err.ssl` == 5, SSL_ERROR_SYSCALL, helpfully commented "look at error stack/return value/errno" in openssl/ssl.h 😅

I'm a bit suspicious about `s->errorhandler()` which is some old convention (git blame: 8 years ago), commented "checks errno, returns NULL, set a Python exception", but at this point, we know that errno is 0, so why call it?

I'm thinking to just change that to SSLEOFError, but I wonder if something else might break?
msg363333 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-03-04 07:26
https://github.com/python/cpython/pull/18772 posted
msg364067 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-03-13 02:29
If someone can review https://github.com/python/cpython/pull/18772 then pretty-please review 🙏
msg367335 - (view) Author: Dima Tisnek (Dima.Tisnek) * Date: 2020-04-27 00:03
I know Christian is very busy, so what can I do to have this patch reviewed?
* it's concise
* there's a reproducer
History
Date User Action Args
2020-05-13 00:02:56jabsetnosy: + jab
2020-04-27 08:59:10remi.lapeyresetnosy: + remi.lapeyre
2020-04-27 00:03:30Dima.Tisneksetmessages: + msg367335
2020-03-13 02:29:53Dima.Tisneksetmessages: + msg364067
2020-03-04 07:26:14Dima.Tisneksetmessages: + msg363333
2020-03-04 07:25:53Dima.Tisneksetkeywords: + patch
stage: needs patch -> patch review
pull_requests: + pull_request18130
2020-03-04 06:50:39Dima.Tisneksetmessages: + msg363329
2020-03-04 02:17:23Dima.Tisneksetmessages: + msg363322
versions: + Python 3.9
2020-03-04 01:21:14Dima.Tisneksetmessages: + msg363318
2020-03-03 19:39:23shevissetnosy: + shevis
2019-06-20 00:19:49Dima.Tisneksetnosy: + Dima.Tisnek
2019-02-27 07:04:48Safihresetnosy: + Safihre
messages: + msg336732
2018-12-31 01:10:19gregory.p.smithsetstage: needs patch
2018-12-31 01:09:15gregory.p.smithsetversions: - Python 3.5, Python 3.6
2018-12-31 01:08:59gregory.p.smithsetversions: + Python 3.6, Python 3.7, Python 3.8
2018-12-31 01:08:26gregory.p.smithsetnosy: + gregory.p.smith
messages: + msg332779
2018-10-20 00:04:29Ben.Darnellsetnosy: + Ben.Darnell
messages: + msg328093
2018-01-22 20:19:49xgdomingosetnosy: + xgdomingo
2017-08-05 20:07:04nikratiosetmessages: + msg299793
2017-08-05 01:49:39martin.pantersetnosy: + martin.panter
messages: + msg299766
2017-08-04 19:16:41nikratiocreate