Add support for named constants in the --ssl-version flag

Fixes #1114

Co-Authored-By: Brett Randall <javabrett@gmail.com>
Signed-off-by: Brett Randall <javabrett@gmail.com>
This commit is contained in:
Berker Peksag 2017-02-06 09:40:10 +03:00
parent 3627c1cff5
commit c66957bbe9
3 changed files with 85 additions and 2 deletions

1
THANKS
View File

@ -31,6 +31,7 @@ Berker Peksag <berker.peksag@gmail.com>
bninja <andrew@poundpay.com>
Bob Hagemann <bob+code@twilio.com>
Bobby Beckmann <bobby@macs-MacBook-Pro.local>
Brett Randall <javabrett@gmail.com>
Brian Rosner <brosner@gmail.com>
Bruno Bigras <bigras.bruno@gmail.com>
Caleb Brown <git@calebbrown.id.au>

View File

@ -344,6 +344,28 @@ def validate_pos_int(val):
return val
def validate_ssl_version(val):
ssl_versions = {}
for protocol in [p for p in dir(ssl) if p.startswith("PROTOCOL_")]:
ssl_versions[protocol[9:]] = getattr(ssl, protocol)
if val in ssl_versions:
# string matching PROTOCOL_...
return ssl_versions[val]
try:
intval = validate_pos_int(val)
if intval in ssl_versions.values():
# positive int matching a protocol int constant
return intval
except (ValueError, TypeError):
# negative integer or not an integer
# drop this in favour of the more descriptive ValueError below
pass
raise ValueError("Invalid ssl_version: %s. Valid options: %s"
% (val, ', '.join(ssl_versions)))
def validate_string(val):
if val is None:
return None
@ -1861,14 +1883,31 @@ class SSLVersion(Setting):
name = "ssl_version"
section = "SSL"
cli = ["--ssl-version"]
validator = validate_pos_int
validator = validate_ssl_version
default = ssl.PROTOCOL_SSLv23
desc = """\
SSL version to use (see stdlib ssl module's)
SSL version to use.
============= ============
--ssl-version Description
============= ============
SSLv3 SSLv3 is not-secure and is strongly discouraged.
SSLv23 Alias for TLS. Deprecated in Python 3.6, use TLS.
TLS Negotiate highest possible version between client/server.
Can yield SSL. (Python 3.6+)
TLSv1 TLS 1.0
TLSv1_1 TLS 1.1 (Python 3.4+)
TLSv2 TLS 1.2 (Python 3.4+)
TLS_SERVER Auto-negotiate the highest protocol version like TLS,
but only support server-side SSLSocket connections.
(Python 3.6+)
.. versionchanged:: 19.7
The default value has been changed from ``ssl.PROTOCOL_TLSv1`` to
``ssl.PROTOCOL_SSLv23``.
.. versionchanged:: 20.0
This setting now accepts string names based on ``ssl.PROTOCOL_``
constants.
"""
class CertReqs(Setting):

View File

@ -386,3 +386,46 @@ def test_umask_config(options, expected):
with AltArgs(cmdline):
app = NoConfigApp()
assert app.cfg.umask == expected
@pytest.mark.parametrize("options, expected", [
(["--ssl-version", "SSLv23"], 2),
(["--ssl-version", "TLSv1"], 3),
(["--ssl-version", "2"], 2),
(["--ssl-version", "3"], 3),
])
def test_ssl_version_named_constants_python3(options, expected):
_test_ssl_version(options, expected)
@pytest.mark.skipif(sys.version_info < (3, 6),
reason="requires python3.6+")
@pytest.mark.parametrize("options, expected", [
(["--ssl-version", "TLS"], 2),
(["--ssl-version", "TLSv1_1"], 4),
(["--ssl-version", "TLSv1_2"], 5),
(["--ssl-version", "TLS_SERVER"], 17),
])
def test_ssl_version_named_constants_python36(options, expected):
_test_ssl_version(options, expected)
@pytest.mark.parametrize("ssl_version", [
"FOO",
"-99",
"99991234"
])
def test_ssl_version_bad(ssl_version):
c = config.Config()
with pytest.raises(ValueError) as exc:
c.set("ssl_version", ssl_version)
assert 'Valid options' in str(exc.value)
assert "TLSv" in str(exc.value)
def _test_ssl_version(options, expected):
cmdline = ["prog_name"]
cmdline.extend(options)
with AltArgs(cmdline):
app = NoConfigApp()
assert app.cfg.ssl_version == expected