[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [flashproxy/master] Use M2Crypto connect in place of Python ssl.wrap_socket.
commit 454b735af24797ef639affd69c933d1d28717764
Author: David Fifield <david@xxxxxxxxxxxxxxx>
Date: Thu Jul 11 14:33:52 2013 -0700
Use M2Crypto connect in place of Python ssl.wrap_socket.
ssl.wrap_socket doesn't provide enough access to the certificate chain;
you can do getpeercert but you can't get at intermediate certificates.
I tried to copy the important OpenSSL calls from newPySSLObject in
http://svn.python.org/projects/python/trunk/Modules/_ssl.c, which is
what gets called indirectly when you do ssl.wrap_socket.
---
facilitator/facilitator-email-poller | 37 +++++++++++++++++++++++++++------
flashproxy-reg-appspot | 38 ++++++++++++++++++++++++++++------
flashproxy-reg-email | 19 +++++++++++------
3 files changed, 76 insertions(+), 18 deletions(-)
diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller
index 2b03799..a2b5cd6 100755
--- a/facilitator/facilitator-email-poller
+++ b/facilitator/facilitator-email-poller
@@ -19,7 +19,7 @@ import time
import fac
from hashlib import sha1
-from M2Crypto import X509
+from M2Crypto import SSL, X509
DEFAULT_IMAP_HOST = "imap.gmail.com"
DEFAULT_IMAP_PORT = 993
@@ -83,15 +83,41 @@ class options(object):
imaplib_debug = False
use_certificate_pin = True
+# Like socket.create_connection in that it tries resolving different address
+# families, but doesn't connect the socket.
+def create_socket(address, timeout = None, source_address = None):
+ host, port = address
+ addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
+ if not addrs:
+ raise error("getaddrinfo returns an empty list")
+ err = None
+ for addr in addrs:
+ try:
+ s = socket.socket(addr[0], addr[1], addr[2])
+ if timeout is not None and type(timeout) == float:
+ s.settimeout(timeout)
+ if source_address is not None:
+ s.bind(source_address)
+ return s
+ except Exception, e:
+ err = e
+ raise err
+
class IMAP4_SSL_REQUIRED(imaplib.IMAP4_SSL):
"""A subclass of of IMAP4_SSL that uses ssl_version=ssl.PROTOCOL_TLSv1 and
cert_reqs=ssl.CERT_REQUIRED."""
def open(self, host = "", port = imaplib.IMAP4_SSL_PORT):
+ ctx = SSL.Context("tlsv1")
+ ctx.set_verify(SSL.verify_peer, 2)
+ ret = ctx.load_verify_locations(self.certfile)
+ assert ret == 1
+
self.host = host
self.port = port
- self.sock = socket.create_connection((host, port))
- self.sslobj = ssl.wrap_socket(self.sock, ssl_version=ssl.PROTOCOL_TLSv1,
- cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.certfile)
+ self.sock = create_socket((self.host, self.port))
+
+ self.sslobj = SSL.Connection(ctx, self.sock)
+ self.sslobj.connect((self.host, self.port))
self.file = self.sslobj.makefile('rb')
def usage(f = sys.stdout):
@@ -337,8 +363,7 @@ def imap_login():
ca_certs_file.close()
# Check that the public key is what we expect.
- cert_der = imap.ssl().getpeercert(binary_form=True)
- cert = X509.load_cert_string(cert_der, format=X509.FORMAT_DER)
+ cert = imap.ssl().get_peer_cert()
pubkey_der = cert.get_pubkey().as_der()
pubkey_digest = sha1(pubkey_der).digest()
diff --git a/flashproxy-reg-appspot b/flashproxy-reg-appspot
index 16d0e7f..fc960e9 100755
--- a/flashproxy-reg-appspot
+++ b/flashproxy-reg-appspot
@@ -16,9 +16,10 @@ import urllib2
from hashlib import sha1
try:
- from M2Crypto import X509
+ from M2Crypto import SSL, X509
except ImportError:
# Defer the error reporting so that --help works even without M2Crypto.
+ SSL = None
X509 = None
DEFAULT_REMOTE_ADDRESS = None
@@ -187,29 +188,54 @@ def generate_url(addr):
raise ValueError("%s exited with status %d" % (FLASHPROXY_REG_URL, p.returncode))
return stdout.strip()
+# Like socket.create_connection in that it tries resolving different address
+# families, but doesn't connect the socket.
+def create_socket(address, timeout = None, source_address = None):
+ host, port = address
+ addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
+ if not addrs:
+ raise error("getaddrinfo returns an empty list")
+ err = None
+ for addr in addrs:
+ try:
+ s = socket.socket(addr[0], addr[1], addr[2])
+ if timeout is not None and type(timeout) == float:
+ s.settimeout(timeout)
+ if source_address is not None:
+ s.bind(source_address)
+ return s
+ except Exception, e:
+ err = e
+ raise err
+
# Certificate validation and pinning for urllib2. Inspired by
# http://web.archive.org/web/20110125104752/http://www.muchtooscrawled.com/2010/03/https-certificate-verification-in-python-with-urllib2/.
class PinHTTPSConnection(httplib.HTTPSConnection):
def connect(self):
- sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
+ sock = create_socket((self.host, self.port), self.timeout, self.source_address)
if self._tunnel_host:
self.sock = sock
self._tunnel()
+ ctx = SSL.Context("tlsv1")
+ ctx.set_verify(SSL.verify_peer, 2)
+
ca_certs_fd, ca_certs_path = tempfile.mkstemp(prefix="flashproxy-reg-appspot-",
dir=get_state_dir(), suffix=".crt")
try:
os.write(ca_certs_fd, CA_CERTS)
os.close(ca_certs_fd)
- self.sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1,
- cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path)
+ ret = ctx.load_verify_locations(ca_certs_path)
+ assert ret == 1
finally:
os.unlink(ca_certs_path)
+ self.sock = SSL.Connection(ctx, sock)
+ self.sock.connect((self.host, self.port))
+
# Check that the public key is what we expect.
- cert_der = self.sock.getpeercert(binary_form=True)
- cert = X509.load_cert_string(cert_der, format=X509.FORMAT_DER)
+ cert = self.sock.get_peer_cert()
pubkey_der = cert.get_pubkey().as_der()
pubkey_digest = sha1(pubkey_der).digest()
diff --git a/flashproxy-reg-email b/flashproxy-reg-email
index 2d3cba9..a3c27ad 100755
--- a/flashproxy-reg-email
+++ b/flashproxy-reg-email
@@ -13,7 +13,7 @@ import tempfile
from hashlib import sha1
try:
- from M2Crypto import BIO, RSA, X509
+ from M2Crypto import BIO, RSA, SSL, X509
except ImportError:
# Defer the error reporting so that --help works even without M2Crypto.
X509 = None
@@ -257,6 +257,9 @@ if options.debug:
smtp.set_debuglevel(1)
try:
+ ctx = SSL.Context("tlsv1")
+ ctx.set_verify(SSL.verify_peer, 2)
+
ca_certs_fd, ca_certs_path = tempfile.mkstemp(prefix="flashproxy-reg-email-",
dir=get_state_dir(), suffix=".crt")
try:
@@ -270,15 +273,19 @@ try:
code, msg = smtp.docmd("STARTTLS")
if code != 220:
raise ValueError("Got code %d after STARTTLS" % code)
- smtp.sock = ssl.wrap_socket(smtp.sock, ssl_version=ssl.PROTOCOL_TLSv1,
- cert_reqs=ssl.CERT_REQUIRED, ca_certs=ca_certs_path)
- smtp.file = smtp.sock.makefile()
+ ret = ctx.load_verify_locations(ca_certs_path)
+ assert ret == 1
finally:
os.unlink(ca_certs_path)
+ smtp.sock = SSL.Connection(ctx, smtp.sock)
+ smtp.sock.setup_ssl()
+ smtp.sock.set_connect_state()
+ smtp.sock.connect_ssl()
+ smtp.file = smtp.sock.makefile()
+
# Check that the public key is what we expect.
- cert_der = smtp.sock.getpeercert(binary_form=True)
- cert = X509.load_cert_string(cert_der, format=X509.FORMAT_DER)
+ cert = smtp.sock.get_peer_cert()
pubkey_der = cert.get_pubkey().as_der()
pubkey_digest = sha1(pubkey_der).digest()
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits