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: SSL socket timeout not set after client connects via accept
Type: behavior Stage:
Components: Versions: Python 3.11, Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: tomazas
Priority: normal Keywords:

Created on 2022-01-25 12:38 by tomazas, last changed 2022-04-11 14:59 by admin.

Files
File name Uploaded Description Edit
https.py tomazas, 2022-01-25 12:38
Messages (1)
msg411585 - (view) Author: (tomazas) Date: 2022-01-25 12:38
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-04-11 14:59:55adminsetgithub: 90676
2022-01-25 12:38:41tomazascreate