Forcing Mechanize to use SSLv3

佐手、 提交于 2019-12-23 16:32:14

问题


How would you force mechanize to use SSLv3 for HTTPS URLs that require it? If I try to use mechanize with all SSLv3-only URLs, I get the error:

URLError: <urlopen error [Errno 1] _ssl.c:504: error:140773E8:SSL routines:SSL23_GET_SERVER_HELLO:reason(1000)>

回答1:


A dirty answer... not requiring patching.

import ssl
from ssl import PROTOCOL_SSLv23, PROTOCOL_SSLv3, CERT_NONE, SSLSocket

def monkey_wrap_socket(sock, keyfile=None, certfile=None,
                server_side=False, cert_reqs=CERT_NONE,
                ssl_version=PROTOCOL_SSLv23, ca_certs=None,
                do_handshake_on_connect=True,
                suppress_ragged_eofs=True, ciphers=None):
    ssl_version=PROTOCOL_SSLv3
    return SSLSocket(sock, keyfile=keyfile, certfile=certfile,
                     server_side=server_side, cert_reqs=cert_reqs,
                     ssl_version=ssl_version, ca_certs=ca_certs,
                     do_handshake_on_connect=do_handshake_on_connect,
                     suppress_ragged_eofs=suppress_ragged_eofs,
                     ciphers=ciphers)

ssl.wrap_socket = monkey_wrap_socket

... before your code.




回答2:


The last comment on the Python issue Eiyrioü von Kauyf mentions above is the solution I implemented in my forked version of mechanize. The diff of mechanize/_opener.py follows. It fixes mechanize.urlopen(), but not mechanize.Browser()'s open() method:

diff --git a/mechanize/_opener.py b/mechanize/_opener.py
index ad8412d..e6d1ebc 100644
--- a/mechanize/_opener.py
+++ b/mechanize/_opener.py
@@ -25,9 +25,27 @@ import _rfc3986
 import _sockettimeout
 import _urllib2_fork
 from _util import isstringlike
+import ssl, socket

 open_file = open

+class HTTPSConnectionV3(httplib.HTTPSConnection):
+    def __init__(self, *args, **kwargs):
+        httplib.HTTPSConnection.__init__(self, *args, **kwargs)
+
+    def connect(self):
+        sock = socket.create_connection((self.host, self.port), self.timeout)
+        if self._tunnel_host:
+            self.sock = sock
+            self._tunnel()
+        try:
+            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv3)
+        except ssl.SSLError, e:
+            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version=ssl.PROTOCOL_SSLv23)
+
+class HTTPSHandlerV3(urllib2.HTTPSHandler):
+    def https_open(self, req):
+        return self.do_open(HTTPSConnectionV3, req)

 class ContentTooShortError(urllib2.URLError):
     def __init__(self, reason, result):
@@ -370,7 +388,7 @@ class OpenerFactory:
         _urllib2_fork.HTTPErrorProcessor,
         ]
     if hasattr(httplib, 'HTTPS'):
-        default_classes.append(_urllib2_fork.HTTPSHandler)
+        default_classes.append(HTTPSHandlerV3)
     handlers = []
     replacement_handlers = []



回答3:


You can monkey-patch ssl.wrap_socket() to use TLSv1, which, after the Poodle vulnerability, seems to be the only viable left. This will force all SSL connections to use TLSv1 regardless of the higher level library.

import ssl
from functools import wraps
def sslwrap(func):
    @wraps(func)
    def bar(*args, **kw):
        kw['ssl_version'] = ssl.PROTOCOL_TLSv1
        return func(*args, **kw)
    return bar

ssl.wrap_socket = sslwrap(ssl.wrap_socket)


来源:https://stackoverflow.com/questions/17927339/forcing-mechanize-to-use-sslv3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!