Skip to content

Commit 5737721

Browse files
committed
Bring back SSL option validation on startup by introducing handlers.validate_ssl_options
1 parent 3ab8723 commit 5737721

File tree

3 files changed

+30
-24
lines changed

3 files changed

+30
-24
lines changed

pyftpdlib/handlers.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3469,17 +3469,7 @@ def verify_certs_callback(self, connection, x509,
34693469

34703470
def get_ssl_context(self):
34713471
if self.ssl_context is None:
3472-
if self.certfile is None:
3473-
raise ValueError("at least certfile must be specified")
3474-
self.ssl_context = SSL.Context(self.ssl_protocol)
3475-
if self.ssl_protocol != SSL.SSLv2_METHOD:
3476-
self.ssl_context.set_options(SSL.OP_NO_SSLv2)
3477-
else:
3478-
warnings.warn("SSLv2 protocol is insecure", RuntimeWarning)
3479-
self.ssl_context.use_certificate_chain_file(self.certfile)
3480-
if not self.keyfile:
3481-
self.keyfile = self.certfile
3482-
self.ssl_context.use_privatekey_file(self.keyfile)
3472+
self.ssl_context = self.validate_ssl_options()
34833473
if self.client_certfile is not None:
34843474
from OpenSSL.SSL import VERIFY_CLIENT_ONCE
34853475
from OpenSSL.SSL import VERIFY_FAIL_IF_NO_PEER_CERT
@@ -3488,16 +3478,32 @@ def get_ssl_context(self):
34883478
VERIFY_FAIL_IF_NO_PEER_CERT |
34893479
VERIFY_CLIENT_ONCE,
34903480
self.verify_certs_callback)
3491-
from OpenSSL.SSL import OP_NO_TICKET
3492-
from OpenSSL.SSL import SESS_CACHE_OFF
3493-
self.ssl_context.load_verify_locations(
3494-
self.client_certfile)
3495-
self.ssl_context.set_session_cache_mode(SESS_CACHE_OFF)
3496-
self.ssl_options = self.ssl_options | OP_NO_TICKET
3497-
if self.ssl_options:
3498-
self.ssl_context.set_options(self.ssl_options)
34993481
return self.ssl_context
35003482

3483+
@classmethod
3484+
def validate_ssl_options(cls):
3485+
if cls.certfile is None:
3486+
raise ValueError("at least certfile must be specified")
3487+
ssl_context = SSL.Context(cls.ssl_protocol)
3488+
if cls.ssl_protocol != SSL.SSLv2_METHOD:
3489+
ssl_context.set_options(SSL.OP_NO_SSLv2)
3490+
else:
3491+
warnings.warn("SSLv2 protocol is insecure", RuntimeWarning)
3492+
ssl_context.use_certificate_chain_file(cls.certfile)
3493+
if not cls.keyfile:
3494+
cls.keyfile = cls.certfile
3495+
ssl_context.use_privatekey_file(cls.keyfile)
3496+
if cls.client_certfile is not None:
3497+
from OpenSSL.SSL import OP_NO_TICKET
3498+
from OpenSSL.SSL import SESS_CACHE_OFF
3499+
ssl_context.load_verify_locations(
3500+
cls.client_certfile)
3501+
ssl_context.set_session_cache_mode(SESS_CACHE_OFF)
3502+
cls.ssl_options = cls.ssl_options | OP_NO_TICKET
3503+
if cls.ssl_options:
3504+
ssl_context.set_options(cls.ssl_options)
3505+
return ssl_context
3506+
35013507
# --- overridden methods
35023508

35033509
def flush_account(self):

pyftpdlib/servers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ def __init__(self, address_or_socket, handler, ioloop=None, backlog=100):
104104
self.ip_map = []
105105
# in case of FTPS class not properly configured we want errors
106106
# to be raised here rather than later, when client connects
107-
# if hasattr(handler, 'get_ssl_context'):
108-
# handler.get_ssl_context(handler)
107+
if hasattr(handler, 'validate_ssl_options'):
108+
handler.validate_ssl_options()
109109
if callable(getattr(address_or_socket, 'listen', None)):
110110
sock = address_or_socket
111111
sock.setblocking(0)

pyftpdlib/test/test_functional_ssl.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,15 @@ def try_protocol_combo(self, server_protocol, client_protocol):
370370
# for proto in protos:
371371
# self.try_protocol_combo(ssl.PROTOCOL_TLSv1, proto)
372372

373-
# On OSX TLS_FTPHandler.get_ssl_context()._context does not exist.
373+
# On OSX TLS_FTPHandler.validate_ssl_options()._context does not exist.
374374
@unittest.skipIf(OSX, "can't get options on OSX")
375375
def test_ssl_options(self):
376376
from OpenSSL import SSL
377377
from OpenSSL._util import lib
378378
from pyftpdlib.handlers import TLS_FTPHandler
379379
try:
380380
TLS_FTPHandler.ssl_context = None
381-
ctx = TLS_FTPHandler.get_ssl_context()
381+
ctx = TLS_FTPHandler.validate_ssl_options()
382382
# Verify default opts.
383383
with contextlib.closing(socket.socket()) as s:
384384
s = SSL.Connection(ctx, s)
@@ -392,7 +392,7 @@ def test_ssl_options(self):
392392
# ssl_proto is set to SSL.SSLv23_METHOD).
393393
TLS_FTPHandler.ssl_context = None
394394
TLS_FTPHandler.ssl_options = None
395-
ctx = TLS_FTPHandler.get_ssl_context()
395+
ctx = TLS_FTPHandler.validate_ssl_options()
396396
with contextlib.closing(socket.socket()) as s:
397397
s = SSL.Connection(ctx, s)
398398
opts = lib.SSL_CTX_get_options(ctx._context)

0 commit comments

Comments
 (0)