Skip to content

Commit

Permalink
Add support for named constants in the --ssl-version flag
Browse files Browse the repository at this point in the history
Fixes #1114

Co-Authored-By: Brett Randall <javabrett@gmail.com>
Signed-off-by: Brett Randall <javabrett@gmail.com>
  • Loading branch information
berkerpeksag and javabrett committed Oct 31, 2018
1 parent 3627c1c commit c66957b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
1 change: 1 addition & 0 deletions THANKS
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
43 changes: 41 additions & 2 deletions gunicorn/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
43 changes: 43 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit c66957b

Please sign in to comment.