Hi,
I'm updating Python to OpenSSL 4 and I get a different error between OpenSSL 3 (3.5.4) and OpenSSL 4 (4.0.0) on SSL_read_ex() on the TLS client after the TLS server closes the socket.
When the server closes the socket (with sslconn.shutdown(socket.SHUT_WR); sslconn.close()), the first SSL_read_ex() on the client fails with SSL_R_UNEXPECTED_EOF_WHILE_READING (same behavior on OpenSSL 3 and OpenSSL 4):
SSL_get_error()=SSL_ERROR_SSL
ERR_GET_LIB()=ERR_LIB_SSL
ERR_GET_REASON()=SSL_R_UNEXPECTED_EOF_WHILE_READING
This error is helpful. My problem is on the second SSL_read_ex() on the client, I get a different error between OpenSSL 3 and OpenSSL 4:
- OpenSSL 3:
SSL_get_error()=SSL_ERROR_SYSCALL, ERR_peek_last_error()=0. Python raises a SSLEOFError in this case (behaves correctly).
- OpenSSL 4:
SSL_get_error()=SSL_ERROR_SSL, ERR_peek_last_error()=0. Python raises a generic SSLError("A failure in the SSL library occurred") in this case (which is unexpected).
OpenSSL 4 sets a generic SSL_ERROR_SSL error with ERR_peek_last_error()=0. It's not helpful to detect an "EOF".
My question is if the different error on OpenSSL 4 was made on purpose, or if it's an issue in OpenSSL 4?
If you want to reproduce my issue, get the Python script:
Details
import os.path
import socket
import ssl
import threading
CERT = os.path.join('Lib', 'test', 'certdata', 'keycert.pem')
HOST = '127.0.0.1'
HOSTNAME = 'localhost'
class Server(threading.Thread):
def __init__(self):
super().__init__()
self.listening = threading.Event()
self.address = None
def run(self):
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(CERT)
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
server_sock.bind((HOST, 0))
server_sock.listen(5)
self.address = server_sock.getsockname()
self.listening.set()
sock, addr = server_sock.accept()
sslconn = context.wrap_socket(sock, server_side=True)
request = b''
while True:
chunk = sslconn.recv(65537)
request += chunk
if b'\r\n\r\n' in request:
break
print(f"server got request: {request!r}")
print("server sendall")
sslconn.sendall(
b'HTTP/1.0 200 OK\r\n'
b'Server: TestHTTP/ Python/3.15.0a8+\r\n'
b'Date: Thu, 16 Apr 2026 12:42:37 GMT\r\n'
b'Content-type: text/plain\r\n\r\n')
sslconn.sendall(b'we care a bit')
print("server shutdown write")
sslconn.shutdown(socket.SHUT_WR)
print("server close socket")
sslconn.close()
server_sock.close()
def main():
server = Server()
server.start()
server.listening.wait()
port = server.address[1]
context = ssl.create_default_context(cafile=CERT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, port))
sslsock = context.wrap_socket(sock, server_hostname=HOSTNAME)
sslsock.sendall(b'GET /bizarre HTTP/1.0\r\n\r\n')
sslobj = sslsock._sslobj
def read(prefix, sslobj):
try:
data = sslobj.read(1024)
result = repr(data)
except ssl.SSLError as exc:
result = f'<{exc!r}>'
print(prefix, result)
for i in range(1, 5):
read(f"client read #{i}:", sslobj)
sslsock.close()
server.join()
if __name__ == "__main__":
main()
And run these commands on Linux:
git clone https://github.com/python/cpython --depth=1
cd cpython/
# Build OpenSSL 4 in ~/multissl/openssl/4.0.0/
python3 Tools/ssl/multissltests.py --steps=library --base-directory $HOME/multissl --openssl 4.0.0 --system Linux
./configure --with-pydebug --with-openssl=$HOME/multissl/openssl/4.0.0/
LD_LIBRARY_PATH=~/multissl/openssl/4.0.0/lib64/ make
LD_LIBRARY_PATH=~/multissl/openssl/4.0.0/lib64/ ./python script.py
Victor
Hi,
I'm updating Python to OpenSSL 4 and I get a different error between OpenSSL 3 (3.5.4) and OpenSSL 4 (4.0.0) on
SSL_read_ex()on the TLS client after the TLS server closes the socket.When the server closes the socket (with
sslconn.shutdown(socket.SHUT_WR); sslconn.close()), the firstSSL_read_ex()on the client fails withSSL_R_UNEXPECTED_EOF_WHILE_READING(same behavior on OpenSSL 3 and OpenSSL 4):SSL_get_error()=SSL_ERROR_SSLERR_GET_LIB()=ERR_LIB_SSLERR_GET_REASON()=SSL_R_UNEXPECTED_EOF_WHILE_READINGThis error is helpful. My problem is on the second
SSL_read_ex()on the client, I get a different error between OpenSSL 3 and OpenSSL 4:SSL_get_error()=SSL_ERROR_SYSCALL,ERR_peek_last_error()=0. Python raises aSSLEOFErrorin this case (behaves correctly).SSL_get_error()=SSL_ERROR_SSL,ERR_peek_last_error()=0. Python raises a genericSSLError("A failure in the SSL library occurred")in this case (which is unexpected).OpenSSL 4 sets a generic
SSL_ERROR_SSLerror withERR_peek_last_error()=0. It's not helpful to detect an "EOF".My question is if the different error on OpenSSL 4 was made on purpose, or if it's an issue in OpenSSL 4?
If you want to reproduce my issue, get the Python script:
Details
And run these commands on Linux:
Victor