Skip to content

Commit 3008415

Browse files
Nik Vdjc
authored andcommitted
Add disable_ssl_verification() method to Session class
Python 2.7.9 has started performing SSL verification by default, which made it impossible to connect to couchdb instances with self-signed certs over SSL. Setting this flag true re-enables the pre 2.7.9 behavior.
1 parent 438c80f commit 3008415

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

couchdb/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@ class Database(object):
271271
2
272272
273273
>>> del server['python-tests']
274+
275+
If you need to connect to a database with an unverified or self-signed SSL
276+
certificate, you can re-initialize your ConnectionPool as follows (only
277+
applicable for Python 2.7.9+):
278+
279+
>>> db.resource.session.disable_ssl_verification()
274280
"""
275281

276282
def __init__(self, url, name=None, session=None):

couchdb/http.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import socket
1818
import time
1919
import sys
20+
import ssl
2021

2122
try:
2223
from threading import Lock
@@ -53,7 +54,7 @@ class NagleMixin:
5354
5455
Based on code originally copied from Python 2.7's httplib module.
5556
"""
56-
57+
5758
def endheaders(self, message_body=None):
5859
if self.__dict__['_HTTPConnection__state'] == _CS_REQ_STARTED:
5960
self.__dict__['_HTTPConnection__state'] = _CS_REQ_SENT
@@ -216,10 +217,25 @@ def __init__(self, cache=None, timeout=None, max_redirects=5,
216217
self.cache = cache
217218
self.max_redirects = max_redirects
218219
self.perm_redirects = {}
219-
self.connection_pool = ConnectionPool(timeout)
220+
self._disable_ssl_verification = False
221+
self._timeout = timeout
222+
self.connection_pool = ConnectionPool(
223+
self._timeout,
224+
disable_ssl_verification=self._disable_ssl_verification)
220225
self.retry_delays = list(retry_delays) # We don't want this changing on us.
221226
self.retryable_errors = set(retryable_errors)
222227

228+
def disable_ssl_verification(self):
229+
"""
230+
Disable verification of SSL certificates and re-initialize the ConnectionPool.
231+
Only applicable on Python 2.7.9+ as previous versions of Python don't verify
232+
SSL certs.
233+
234+
:return:
235+
"""
236+
self._disable_ssl_verification = True
237+
self.connection_pool = ConnectionPool(self._timeout, disable_ssl_verification=self._disable_ssl_verification)
238+
223239
def request(self, method, url, body=None, headers=None, credentials=None,
224240
num_redirects=0):
225241
if url in self.perm_redirects:
@@ -420,11 +436,23 @@ def _clean(self):
420436
self.by_url = dict(ls[-self.keep_size:])
421437

422438

439+
class InsecureHTTPSConnection(HTTPSConnection):
440+
""" Wrapper class to create an HTTPSConnection without SSl verification (the default behavior in
441+
Python < 2.7.9).
442+
443+
See: https://docs.python.org/2/library/httplib.html#httplib.HTTPSConnection
444+
"""
445+
def __init__(self, *a, **k):
446+
k['context'] = ssl._create_unverified_context()
447+
HTTPSConnection.__init__(self, *a, **k)
448+
449+
423450
class ConnectionPool(object):
424451
"""HTTP connection pool."""
425452

426-
def __init__(self, timeout):
453+
def __init__(self, timeout, disable_ssl_verification=False):
427454
self.timeout = timeout
455+
self.disable_ssl_verification = disable_ssl_verification
428456
self.conns = {} # HTTP connections keyed by (scheme, host)
429457
self.lock = Lock()
430458

@@ -448,7 +476,10 @@ def get(self, url):
448476
if scheme == 'http':
449477
cls = HTTPConnection
450478
elif scheme == 'https':
451-
cls = HTTPSConnection
479+
if self.disable_ssl_verification:
480+
cls = InsecureHTTPSConnection
481+
else:
482+
cls = HTTPSConnection
452483
else:
453484
raise ValueError('%s is not a supported scheme' % scheme)
454485
conn = cls(host, timeout=self.timeout)

0 commit comments

Comments
 (0)