Opened 10 years ago

Closed 9 years ago

#5684 defect closed wontfix (wontfix)

OpenSSL.SSL.Connection object has no getpeername attribute

Reported by: Nathan M Owned by: Nathan M
Priority: normal Milestone:
Component: core Keywords: SSL Connection
Cc: Branch:


When reactor.connectSSL is used to create an SSL connection, the OpenSSL.SSL.Connection object has no getpeername attribute.

The following code sample can be used to reproduce the problem (change the connectSSL arguments to a valid IP and port where a secure server is accepting connections).

from OpenSSL import SSL
from twisted.internet import reactor, ssl
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver

class MyContextFactory(ssl.ClientContextFactory):

    def _verify(self, connection, x509, errnum, errdepth, ok):
        peername = connection.getpeername()
        print "connected to", peername
        return ok

    def getContext(self):
        ctx = ssl.ClientContextFactory.getContext(self)
        ctx.set_verify(SSL.VERIFY_PEER, self._verify)
        return ctx

class MyClient(LineReceiver):
    def connectionMade(self):

    def lineReceived(self):

class MyClientFactory(ClientFactory):
    protocol = MyClient

    def clientConnectionFailed(self, connector, reason):

    def clientConnectionLost(self, connector, reason):

if __name__ == "__main__":
    reactor.connectSSL('', 12345, MyClientFactory(), MyContextFactory())

This produces an exception:

exceptions.AttributeError: 'NoneType' object has no attribute 'getpeername'

Yet this works...

from OpenSSL import SSL
import socket

context = SSL.Context(SSL.TLSv1_METHOD)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection = SSL.Connection(context, s)
connection.connect(('', 12345))
print "connected to", connection.getpeername()

Change History (6)

comment:1 Changed 10 years ago by Jean-Paul Calderone

Owner: set to Nathan M

I fail to reproduce this problem. Changing the host/port to, I get this output:

connected to ('', 443)

comment:2 Changed 10 years ago by Nathan M

Using I still get the error. I'm running the latest Twisted 12.0.0 code from the svn repo. My pyOpenSSL version is 0.11. You're testing the first code sample, and not the second, correct?

comment:3 Changed 10 years ago by Nathan M

I get the same result with pyOpenSSL version 0.13.

comment:4 Changed 10 years ago by Jean-Paul Calderone

The difference is whether the Twisted memory bio-based transport implementation is in use or not.

Newer versions of Twisted don't let OpenSSL do networking. A consequence is that there is no Connection instance to pass to the verify callback (note that the object passed for the first argument is None, not a Connection object that is missing getpeername).

comment:5 Changed 10 years ago by Nathan M

When memory BIO is in use, is there any way to ascertain peer name in the verify method?

comment:6 Changed 9 years ago by Glyph

Resolution: wontfix
Status: newclosed

You can use the self.transport.getPeer() method, since the "transport" attribute of Protocol is documented to be an ITransport, and an ITransport does not necessarily have a "socket" attribute.

This method has always worked, and is really how you ought to have been doing it all along.

I'm closing this as "wontfix" rather than "invalid", because in some cases this might be a valid observation about compatibility being broken - you didn't have to type "._" to get to it, which in many cases makes it fair game. However, in the case of an attribute with a documented interface, you really can't depend on more attributes than what the interface documentation says, if you want your code to keep working with new implementations of that interface, which the new BIO-based implementation is.

Note: See TracTickets for help on using tickets.