summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGiampaolo RodolĂ  <g.rodola@gmail.com>2010-05-26 18:06:04 (GMT)
committerGiampaolo RodolĂ  <g.rodola@gmail.com>2010-05-26 18:06:04 (GMT)
commita67299e757b69660ec932e4da0a7dd4bfc680f08 (patch)
tree8ed4df6f8163b832625b232b19c46ac12bd26899 /Lib
parent60853211da1d3c450b6371ebfaedade04a908f21 (diff)
downloadcpython-a67299e757b69660ec932e4da0a7dd4bfc680f08.zip
cpython-a67299e757b69660ec932e4da0a7dd4bfc680f08.tar.gz
cpython-a67299e757b69660ec932e4da0a7dd4bfc680f08.tar.bz2
Fix issue #8806: add SSL contexts support to ftplib
Diffstat (limited to 'Lib')
-rw-r--r--Lib/ftplib.py25
-rw-r--r--Lib/test/test_ftplib.py23
2 files changed, 43 insertions, 5 deletions
diff --git a/Lib/ftplib.py b/Lib/ftplib.py
index c25ae2a..b593fa1 100644
--- a/Lib/ftplib.py
+++ b/Lib/ftplib.py
@@ -638,9 +638,17 @@ else:
ssl_version = ssl.PROTOCOL_TLSv1
def __init__(self, host='', user='', passwd='', acct='', keyfile=None,
- certfile=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
+ certfile=None, context=None,
+ timeout=_GLOBAL_DEFAULT_TIMEOUT):
+ if context is not None and keyfile is not None:
+ raise ValueError("context and keyfile arguments are mutually "
+ "exclusive")
+ if context is not None and certfile is not None:
+ raise ValueError("context and certfile arguments are mutually "
+ "exclusive")
self.keyfile = keyfile
self.certfile = certfile
+ self.context = context
self._prot_p = False
FTP.__init__(self, host, user, passwd, acct, timeout)
@@ -657,8 +665,12 @@ else:
resp = self.voidcmd('AUTH TLS')
else:
resp = self.voidcmd('AUTH SSL')
- self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile,
- ssl_version=self.ssl_version)
+ if self.context is not None:
+ self.sock = self.context.wrap_socket(self.sock)
+ else:
+ self.sock = ssl.wrap_socket(self.sock, self.keyfile,
+ self.certfile,
+ ssl_version=self.ssl_version)
self.file = self.sock.makefile(mode='r', encoding=self.encoding)
return resp
@@ -689,8 +701,11 @@ else:
def ntransfercmd(self, cmd, rest=None):
conn, size = FTP.ntransfercmd(self, cmd, rest)
if self._prot_p:
- conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
- ssl_version=self.ssl_version)
+ if self.context is not None:
+ conn = self.context.wrap_socket(conn)
+ else:
+ conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,
+ ssl_version=self.ssl_version)
return conn, size
def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py
index eb33526..9dc06cd 100644
--- a/Lib/test/test_ftplib.py
+++ b/Lib/test/test_ftplib.py
@@ -719,6 +719,29 @@ class TestTLS_FTPClass(TestCase):
finally:
self.client.ssl_version = ssl.PROTOCOL_TLSv1
+ def test_context(self):
+ self.client.quit()
+ ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+ self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE,
+ context=ctx)
+ self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE,
+ context=ctx)
+ self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE,
+ keyfile=CERTFILE, context=ctx)
+
+ self.client = ftplib.FTP_TLS(context=ctx, timeout=2)
+ self.client.connect(self.server.host, self.server.port)
+ self.assertNotIsInstance(self.client.sock, ssl.SSLSocket)
+ self.client.auth()
+ self.assertIs(self.client.sock.context, ctx)
+ self.assertIsInstance(self.client.sock, ssl.SSLSocket)
+
+ self.client.prot_p()
+ sock = self.client.transfercmd('list')
+ self.assertIs(self.client.sock.context, ctx)
+ self.assertIsInstance(sock, ssl.SSLSocket)
+ sock.close()
+
class TestTimeouts(TestCase):