Skip to content
This repository

Added ability to choose SSL version #900

Closed
wants to merge 4 commits into from

3 participants

David Andrzejewski Kenneth Reitz Ian Cordasco
David Andrzejewski

This also acts as a workaround for #827, which in some cases, if you are
connecting to an SSL server that does not support SSLv2 or SSLv3 (and,
for exapmle, only supports TLSv1), would cause an illegal EOL SSL error.
If you select the right SSL protocol version, you won't see this error.

Kenneth, it looks like you tried to fix this in a previous revision by hard-coding the SSL version, and then you rolled it back. This makes it configurable via parameter to requests.requesttype()

David Andrzejewski Added ability to choose SSL version
This also acts as a workaround for #827, which in some cases, if you are
connecting to an SSL server that does not support SSLv2 or SSLv3 (and,
for exapmle, only supports TLSv1), would cause an illegal EOL SSL error.
If you select the right SSL protocol version, you won't see this error.
2f414d0
Ian Cordasco

Pretty sure this is entirely unnecessary

Oh, just set it directly?

Collaborator

Good call. I'm so accustomed from Java to automatically writing getters/setters for everything. I'll go ahead and get that updated.

Collaborator

I did not already know, so thanks! This is actually the very first time I've ever done anything on GitHub.

Collaborator
David Andrzejewski

I made one last change to correct an issue where you could have a crash if Python was built without SSL support.

Also, I've submitted all of these changes to the urllib3 project, and it looks like @shazow is interested in merging, so you should be good there.

David Andrzejewski dandrzejewski closed this October 22, 2012
David Andrzejewski dandrzejewski reopened this October 22, 2012
David Andrzejewski

Interesting - build 802 failed because it timed out after 15 minutes. 803 succeeded, but it finished before 802. So, this pull request is being reported as a failure when it shouldn't be...

Kenneth Reitz
Owner

I won't be merging this at this time. Requests should be able to automatically fall back, just like the web browser.

I'll be adding TransportAdapters soon, and you'll be able to specify advanced options like this.

Kenneth Reitz kennethreitz closed this October 23, 2012
David Andrzejewski

That's the problem. In my environment, on Windows (but not Linux), when I'm connecting to to an HTTPS server that only supports TLSv1/2/3, but NOT SSLv2/3, I get the same error that's reported in #827:

requests.exceptions.SSLError: [Errno 8] _ssl.c:504: EOF occurred in violation of protocol

That's why I submitted this as a workaround.

Kenneth Reitz
Owner

I'll be adding TransportAdapters soon, and you'll be able to specify advanced options like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 4 unique commits by 1 author.

Oct 19, 2012
David Andrzejewski Added ability to choose SSL version
This also acts as a workaround for #827, which in some cases, if you are
connecting to an SSL server that does not support SSLv2 or SSLv3 (and,
for exapmle, only supports TLSv1), would cause an illegal EOL SSL error.
If you select the right SSL protocol version, you won't see this error.
2f414d0
David Andrzejewski Removed unneeded setter for connectionpool.ssl_version aee7b2a
David Andrzejewski Removed call to the setter I removed in the previous commit. 2413492
Oct 22, 2012
David Andrzejewski The previous revision could crash if Python is compiled without the S…
…SL module. Fixed.
d093575
This page is out of date. Refresh to see the latest.
10  requests/models.py
@@ -64,7 +64,8 @@ def __init__(self,
64 64
         _poolmanager=None,
65 65
         verify=None,
66 66
         session=None,
67  
-        cert=None):
  67
+        cert=None,
  68
+        ssl_version=None):
68 69
 
69 70
         #: Dictionary of configurations for this request.
70 71
         self.config = dict(config or [])
@@ -157,6 +158,9 @@ def __init__(self,
157 158
         #: SSL Verification.
158 159
         self.verify = verify
159 160
 
  161
+        #: SSL Version
  162
+        self.ssl_version = ssl_version
  163
+
160 164
         #: SSL Certificate
161 165
         self.cert = cert
162 166
 
@@ -598,6 +602,10 @@ def send(self, anyway=False, prefetch=None):
598 602
             else:
599 603
                 conn.cert_file = self.cert
600 604
 
  605
+        if self.ssl_version:
  606
+            if self.ssl_version is not None:
  607
+                conn.ssl_version = self.ssl_version
  608
+
601 609
         if not self.sent or anyway:
602 610
 
603 611
             # Skip if 'cookie' header is explicitly set.
17  requests/packages/urllib3/connectionpool.py
@@ -76,6 +76,7 @@ class VerifiedHTTPSConnection(HTTPSConnection):
76 76
     """
77 77
     cert_reqs = None
78 78
     ca_certs = None
  79
+    ssl_version = None
79 80
 
80 81
     def set_cert(self, key_file=None, cert_file=None,
81 82
                  cert_reqs='CERT_NONE', ca_certs=None):
@@ -98,7 +99,8 @@ def connect(self):
98 99
         # trusted_root_certs
99 100
         self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
100 101
                                     cert_reqs=self.cert_reqs,
101  
-                                    ca_certs=self.ca_certs)
  102
+                                    ca_certs=self.ca_certs,
  103
+                                    ssl_version=self.ssl_version)
102 104
         if self.ca_certs:
103 105
             match_hostname(self.sock.getpeercert(), self.host)
104 106
 
@@ -493,8 +495,8 @@ class HTTPSConnectionPool(HTTPConnectionPool):
493 495
     :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates,
494 496
     instead of :class:httplib.HTTPSConnection`.
495 497
 
496  
-    The ``key_file``, ``cert_file``, ``cert_reqs``, and ``ca_certs`` parameters
497  
-    are only used if :mod:`ssl` is available and are fed into
  498
+    The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, and ``ssl_version``
  499
+    parameters are only used if :mod:`ssl` is available and are fed into
498 500
     :meth:`ssl.wrap_socket` to upgrade the connection socket into an SSL socket.
499 501
     """
500 502
 
@@ -504,7 +506,7 @@ def __init__(self, host, port=None,
504 506
                  strict=False, timeout=None, maxsize=1,
505 507
                  block=False, headers=None,
506 508
                  key_file=None, cert_file=None,
507  
-                 cert_reqs='CERT_NONE', ca_certs=None):
  509
+                 cert_reqs='CERT_NONE', ca_certs=None, ssl_version=None):
508 510
 
509 511
         super(HTTPSConnectionPool, self).__init__(host, port,
510 512
                                                   strict, timeout, maxsize,
@@ -513,6 +515,7 @@ def __init__(self, host, port=None,
513 515
         self.cert_file = cert_file
514 516
         self.cert_reqs = cert_reqs
515 517
         self.ca_certs = ca_certs
  518
+        self.ssl_version = ssl_version
516 519
 
517 520
     def _new_conn(self):
518 521
         """
@@ -532,6 +535,12 @@ def _new_conn(self):
532 535
         connection = VerifiedHTTPSConnection(host=self.host, port=self.port)
533 536
         connection.set_cert(key_file=self.key_file, cert_file=self.cert_file,
534 537
                             cert_reqs=self.cert_reqs, ca_certs=self.ca_certs)
  538
+
  539
+        if self.ssl_version is None:
  540
+            connection.ssl_version = ssl.PROTOCOL_SSLv23
  541
+        else:
  542
+            connection.ssl_version = self.ssl_version
  543
+
535 544
         return connection
536 545
 
537 546
 
13  requests/sessions.py
@@ -58,7 +58,7 @@ class Session(object):
58 58
 
59 59
     __attrs__ = [
60 60
         'headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks',
61  
-        'params', 'config', 'verify', 'cert', 'prefetch']
  61
+        'params', 'config', 'verify', 'cert', 'prefetch', 'ssl_version']
62 62
 
63 63
     def __init__(self,
64 64
         headers=None,
@@ -71,7 +71,8 @@ def __init__(self,
71 71
         config=None,
72 72
         prefetch=True,
73 73
         verify=True,
74  
-        cert=None):
  74
+        cert=None,
  75
+        ssl_version=None):
75 76
 
76 77
         self.headers = from_key_val_list(headers or [])
77 78
         self.auth = auth
@@ -83,6 +84,7 @@ def __init__(self,
83 84
         self.prefetch = prefetch
84 85
         self.verify = verify
85 86
         self.cert = cert
  87
+        self.ssl_version = ssl_version
86 88
 
87 89
         for (k, v) in list(defaults.items()):
88 90
             self.config.setdefault(k, deepcopy(v))
@@ -133,7 +135,8 @@ def request(self, method, url,
133 135
         config=None,
134 136
         prefetch=None,
135 137
         verify=None,
136  
-        cert=None):
  138
+        cert=None,
  139
+        ssl_version=None):
137 140
 
138 141
         """Constructs and sends a :class:`Request <Request>`.
139 142
         Returns :class:`Response <Response>` object.
@@ -154,6 +157,7 @@ def request(self, method, url,
154 157
         :param prefetch: (optional) whether to immediately download the response content. Defaults to ``True``.
155 158
         :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided.
156 159
         :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
  160
+        :param ssl_version: (optional) The SSL protocol version to use.
157 161
         """
158 162
 
159 163
         method = str(method).upper()
@@ -192,7 +196,8 @@ def request(self, method, url,
192 196
             prefetch=prefetch,
193 197
             verify=verify,
194 198
             cert=cert,
195  
-            _poolmanager=self.poolmanager
  199
+            _poolmanager=self.poolmanager,
  200
+            ssl_version=ssl_version
196 201
         )
197 202
 
198 203
         # merge session cookies into passed-in ones
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.