classification
Title: connect_ex() implementation missing for SSL sockets
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: giampaolo.rodola, pitrou, segfaulthunter
Priority: normal Keywords: patch

Created on 2011-02-26 00:31 by segfaulthunter, last changed 2011-03-01 18:51 by segfaulthunter. This issue is now closed.

Files
File name Uploaded Description Edit
handshake.py segfaulthunter, 2011-02-26 00:31 Minimal example of asynchronous ssl handshakes failing for asynchronously connected sockets.
ssl_connect.patch pitrou, 2011-02-26 00:58
Messages (7)
msg129477 - (view) Author: Florian Mayer (segfaulthunter) Date: 2011-02-26 00:31
The asynchronous do_handshakes fails for sockets that were connected asynchronously. Tested on 2.6, 3.1 and 3.2.

Traceback (most recent call last):
  File "handshake.py", line 17, in <module>
    s.do_handshake()
  File "/usr/lib/python2.6/ssl.py", line 279, in do_handshake
    self._sslobj.do_handshake()
AttributeError: 'NoneType' object has no attribute 'do_handshake'
msg129478 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-02-26 00:39
Ok, one issue is that connect_ex() isn't implemented for SSL sockets, so it defers to the normal implementation instead, which is wrong.

But your still is wrong too. connect_ex() returns an error, meaning the socket isn't connected and you must retry. Here is a working snippet using connect():


def connect():
    try:
        s.connect(('people.csail.mit.edu', 443))
    except socket.error as e:
        if e.errno != errno.EINPROGRESS:
            raise
        return False
    else:
        return True

while not connect():
    select.select([s], [s], [])

while True:
    try:
        select.select([s], [s], [])
        s.do_handshake()
        break
    except ssl.SSLError as err:
        if err.args[0] == ssl.SSL_ERROR_WANT_READ:
            select.select([s], [], [])
        elif err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
            select.select([], [s], [])
        else:
            raise
msg129479 - (view) Author: Florian Mayer (segfaulthunter) Date: 2011-02-26 00:40
A workaround would be exposing _ssl.wrapssl in ssl so that it can be called once the socket is connected and no non-public API had to be used.
msg129480 - (view) Author: Florian Mayer (segfaulthunter) Date: 2011-02-26 00:43
The select call after the connect_ex waits until the connection is done, for the first write event is fired then, so the socket is connected afterwards.
msg129481 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-02-26 00:56
> The select call after the connect_ex waits until the connection is
> done, for the first write event is fired then, so the socket is
> connected afterwards.

You are right. Here is a patch for py3k implementing connect_ex() and solving the issue with the missing "_sslobj" attribute. It makes your script run fine.

(ideally I should add some tests to the patch, at least for connect_ex)
msg129605 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-02-26 23:36
I've committed the patch + some tests in r88664 (3.3), r88665 (3.2) and r88666 (2.7). Thanks for reporting this!
msg129792 - (view) Author: Florian Mayer (segfaulthunter) Date: 2011-03-01 18:51
Thanks for the fast response and for fixing this.
History
Date User Action Args
2011-03-01 18:51:21segfaulthuntersetnosy: pitrou, giampaolo.rodola, segfaulthunter
messages: + msg129792
2011-02-26 23:36:32pitrousetstatus: open -> closed
versions: - Python 3.1
nosy: pitrou, giampaolo.rodola, segfaulthunter
messages: + msg129605

resolution: fixed
stage: patch review -> resolved
2011-02-26 00:58:59pitrousetfiles: + ssl_connect.patch
nosy: pitrou, giampaolo.rodola, segfaulthunter
2011-02-26 00:58:20pitrousetfiles: - ssl_connect.patch
nosy: pitrou, giampaolo.rodola, segfaulthunter
2011-02-26 00:56:53pitrousetfiles: + ssl_connect.patch

nosy: + giampaolo.rodola
messages: + msg129481

keywords: + patch
stage: needs patch -> patch review
2011-02-26 00:43:28segfaulthuntersetnosy: pitrou, segfaulthunter
messages: + msg129480
2011-02-26 00:40:58segfaulthuntersetnosy: pitrou, segfaulthunter
messages: + msg129479
2011-02-26 00:39:53pitrousetnosy: + pitrou
title: Asynchronous ssl handshakes fails for asynchronously connected sockets. -> connect_ex() implementation missing for SSL sockets
messages: + msg129478

versions: + Python 2.7, Python 3.3, - Python 2.6
stage: needs patch
2011-02-26 00:31:12segfaulthuntercreate