2013-07-29 27 views
3

您將如何強制mechanize將SSLv3用於需要它的HTTPS URL?如果我嘗試使用所有的SSLv3只機械化的網址,我得到的錯誤:強制機械化使用SSLv3

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

從下面的錯誤報告,這可能會幫助: http://bugs.python.org/issue11220 此外,我覺得應該有一個''verify_mode''地方的選擇,但我不能在''mechanize''文檔中找到它:/。和''def add_client_certificate(self,url,key_file,cert_file):''in mechanize/_useragent.py可能會有所幫助,但抱歉我找不到任何明確使用現在:( –

+0

@EiyrioüvonKauyf,是的,我偶然發現這就是爲什麼我試圖強制它使用SSLv3,「問題是服務器只嚴格接受SSLv3,urllib和http.client發送SSLv23協議。」他們甚至以自定義的形式爲urllib提供瞭解決方法但我不知道如何適應機械化 – Cerin

回答

1

Eiyrioü馮Kauyf上面提到的Python的問題的最後註釋是我在forked version of mechanize實施的解決方案。 mechanize/_opener.py的差異如下。它修復mechanize.urlopen(),但「不是mechanize.Browser()open()方法:

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 = [] 
+0

非常感謝您的支持,它對我有用 – bernie

2

骯髒的答案......不需要打補丁。

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 

...在您的代碼之前。

+0

Hrmm,對我不起作用,我仍然得到主機名不符合certificateerror – pugmastaflex

0

您可以使用ssl.wrap_socket()來使用TLSv1,它在Poodle漏洞之後似乎是唯一可行的左邊。這將強制所有SSL連接使用TLSv1,而不管更高級別的庫如何。

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)