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.

Author tomazas
Recipients tomazas
Date 2022-01-25.12:38:41
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1643114321.92.0.142343985448.issue46518@roundup.psfhosted.org>
In-reply-to
Content
Once a client connects to a SSL server over socket accept() the newly returned client socket `newsock` is wrapped in SSL context.
Since the new client `newsock` does not have a socket timeout set (i.e. None), the final returned SSL context socket is also assigned `None` socket timeout. Clients are then able to connect to such server and hold the connection indefinitely without sending any data to server (ghosting the server connections).

Problematic excerpt from Lib/ssl.py:
```
    def accept(self):
        """Accepts a new connection from a remote client, and returns
        a tuple containing that new connection wrapped with a server-side
        SSL channel, and the address of the remote client."""

        newsock, addr = super().accept()
        newsock = self.context.wrap_socket(newsock,
                    do_handshake_on_connect=self.do_handshake_on_connect,
                    suppress_ragged_eofs=self.suppress_ragged_eofs,
                    server_side=True)
        return newsock, addr
```

Attached minimal https.py server Python3 example producing the issue.
After the server is working run the bellow ghost client script to produce the issue:

```
# Script implements ghost client (that does not send anything to server but keeps connection active until server socket timeouts or forever if socket timeouts are not working)
# Usage - after https.py server is launched run using: python3 ghost.py
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 443))
print("connected")

while True:
	print("ghosting started")
	data = sock.recv(4096) # read to block
	if not data:
		break
	print(data)
	
print("done.")
```

Possible workarounds:
1. socket.setdefaulttimeout(2) - works but interferes with all possible socket operations 
2. Patch the socket accept() operation and set the timeout value there before doing any socket operations, e.g.:

```
import socket
old_accept = socket.socket.accept
def patch_accept(self):
	newsock, addr = old_accept(self)
	newsock.settimeout(2) # sets the client socket timeout
	print("socket.accept patched")
	return newsock, addr

socket.socket.accept = patch_accept

# TODO: now run all the SSL server socket code here
```
History
Date User Action Args
2022-01-25 12:38:42tomazassetrecipients: + tomazas
2022-01-25 12:38:41tomazassetmessageid: <1643114321.92.0.142343985448.issue46518@roundup.psfhosted.org>
2022-01-25 12:38:41tomazaslinkissue46518 messages
2022-01-25 12:38:41tomazascreate