[Twisted-Python] PyOpenSSL empty socket property
Glyph
glyph at twistedmatrix.com
Sun Sep 8 21:32:19 MDT 2019
Indeed, in Twisted, the SSL.Connection is constructed with a memory BIO. And in fact there may not be a socket in the loop at all!
What are you trying to do with `getpeername()`? Hopefully there's a similar Twisted API that you could work with.
-glyph
> On Sep 5, 2019, at 11:07 PM, Sean DiZazzo <sean.dizazzo at gmail.com> wrote:
>
> Perhaps this line from OpenSSL.SSL.Connection is a clue.
>
> "socket may be None; in this case, the Connection is created with a memory BIO: see the bio_read(), bio_write(), and bio_shutdown() methods."
> https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Connection <https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Connection>
>
> On Wed, Sep 4, 2019 at 1:38 AM Arn Vollebregt <kpn.arn.vollebregt at gmail.com <mailto:kpn.arn.vollebregt at gmail.com>> wrote:
> Hi,
>
> I noticed that PyOpenSSL SNI callbacks (set with ctx.set_tlsext_servername_callback) receive a OpenSSL.SSL.Connection object within Twisted that have an empty _socket property, while this property is actually set when using PyOpenSSL directly. For my use-case this is a problem as I want to call conn._socket.getpeername() to determine the peer's IP address. So I am wondering: why is this behaviour different? And how do I get the peer IP address?
>
> ---console---
> user:~$ sudo python testTwisted.py &
> [3] 32842
> user:~$ curl -s --insecure --key clientPrivateKey.pem --cert clientCertificate.pem https://127.0.0.1 <https://127.0.0.1/> > /dev/null
> 'sniCallback' called.
> conn._socket: None
> 'verifyCallback' called for result 0
> conn._socket: None
> 'verifyCallback' called for result 1
> conn._socket: None
> user:~$ sudo python testPyOpenSSL.py &
> [1] 33270
> user:~$ curl -s --insecure --key clientPrivateKey.pem --cert clientCertificate.pem https://127.0.0.1 <https://127.0.0.1/> > /dev/null
> 'sniCallback' called.
> conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> <class 'OpenSSL.SSL.Connection'>
> 'verifyCallback' called for result 0
> conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> 'verifyCallback' called for result 1
> conn._socket: <socket._socketobject object at 0x7f34c5bd3130>
> 127.0.0.1 - - [29/Aug/2019 11:45:47] "GET / HTTP/1.1" 200 -
> ------
>
> ---testTwisted.py---
> ### Generate server key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout serverPrivateKey.pem -out serverCertificate.pem -subj "/C=''/O=''/OU=''/CN=server"
> ### Generate client key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout clientPrivateKey.pem -out clientCertificate.pem -subj "/C=''/O=''/OU=''/CN=client"
> from __future__ import print_function
> #https://twistedmatrix.com/documents/12.0.0/core/howto/ssl.html <https://twistedmatrix.com/documents/12.0.0/core/howto/ssl.html>
> from OpenSSL import SSL
> from twisted.internet import ssl, reactor
> from twisted.web import server, resource
> from twisted.internet.protocol import Factory, Protocol
>
> def verifyCallback(conn, cert, errno, depth, result):
> print('\'verifyCallback\' called for result ' + str(result))
> print('\tconn._socket: ' + str(conn._socket))
> return True
>
> def sniCallback(conn):
> print('\'sniCallback\' called.')
> print('\tconn._socket: ' + str(conn._socket))
>
> class MainResource(resource.Resource):
> isLeaf = True
>
> def render_GET(self, request):
> request.responseHeaders.addRawHeader("Content-Type", "text/html; charset=utf-8")
> return b"<html><body>Hello World</body></html>"
>
> if __name__ == '__main__':
> myContextFactory = ssl.DefaultOpenSSLContextFactory(
> 'serverPrivateKey.pem',
> 'serverCertificate.pem'
> )
> ctx = myContextFactory.getContext()
> # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify <https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify>
> ctx.set_verify(SSL.VERIFY_PEER, verifyCallback)
> # https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback <https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback>
> ctx.set_tlsext_servername_callback(sniCallback)
>
> site = server.Site(MainResource())
> reactor.listenSSL(443, site, myContextFactory)
> reactor.run()
> ------
>
> ---testPyOpenSSL.py---
> ### Generate server key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout serverPrivateKey.pem -out serverCertificate.pem -subj "/C=''/O=''/OU=''/CN=server"
> ### Generate client key material ###
> # openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout clientPrivateKey.pem -out clientCertificate.pem -subj "/C=''/O=''/OU=''/CN=client"
> from __future__ import print_function
> import socket, sys, os
> from SocketServer import BaseServer
> from BaseHTTPServer import HTTPServer
> from SimpleHTTPServer import SimpleHTTPRequestHandler
> from OpenSSL import SSL
>
> def verifyCallback(conn, cert, errno, depth, result):
> print('\'verifyCallback\' called for result ' + str(result))
> print('\tconn._socket: ' + str(conn._socket))
> return True
>
> def sniCallback(conn):
> print('\'sniCallback\' called.')
> print('\tconn._socket: ' + str(conn._socket))
> print(type(conn))
>
> class SecureHTTPServer(HTTPServer):
> def __init__(self, server_address, HandlerClass):
> BaseServer.__init__(self, server_address, HandlerClass)
> ctx = SSL.Context(SSL.TLSv1_2_METHOD)
> ctx.use_privatekey_file('serverPrivateKey.pem')
> ctx.use_certificate_file('serverCertificate.pem')
> # https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify <https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_verify>
> ctx.set_verify(SSL.VERIFY_PEER, verifyCallback)
> # https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback <https://pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context.set_tlsext_servername_callback>
> ctx.set_tlsext_servername_callback(sniCallback)
> self.socket = SSL.Connection(ctx, socket.socket(self.address_family,self.socket_type))
> self.server_bind()
> self.server_activate()
>
> def shutdown_request(self,request):
> request.shutdown()
>
> class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
> def setup(self):
> self.connection = self.request
> self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
> self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
>
> def do_GET(self):
> self.send_response(200)
> SimpleHTTPRequestHandler.end_headers(self)
> self.wfile.write('<html><body>Hello World</body></html>')
>
> if __name__ == '__main__':
> ip,port = ('0.0.0.0', 443)
> httpd = SecureHTTPServer((ip, port), SecureHTTPRequestHandler)
> httpd.serve_forever()
> ------
>
> (Please note that even though these examples are for Python2 (due to other quirks) I am aiming to implement this in Python3.)
>
> Regards,
>
> Arn
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com <mailto:Twisted-Python at twistedmatrix.com>
> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python <https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> https://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20190908/fb1b5723/attachment-0002.html>
More information about the Twisted-Python
mailing list