Don't hard-code client's TLS versions and ciphers

Client connections no longer override TLS version range and ciphers by
default. Instead clients use the default settings from the system's
crypto policy.

Minimum TLS version is now TLS 1.2. The default crypto policy on
RHEL 8 sets TLS 1.2 as minimum version, while Fedora 31 sets TLS 1.0 as
minimum version. The minimum version is configured with OpenSSL 1.1.1
APIs. Python 3.6 lacks the setters to override the system policy.

The effective minimum version is always TLS 1.2, because FreeIPA
reconfigures Apache HTTPd on Fedora.

Fixes: https://pagure.io/freeipa/issue/8125
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Thomas Woerner <twoerner@redhat.com>
This commit is contained in:
Christian Heimes
2019-11-22 10:42:11 +01:00
parent 0198eca795
commit 639bb71940
6 changed files with 108 additions and 26 deletions

View File

@@ -683,7 +683,7 @@ class TestIPACommand(IntegrationTest):
assert 'Last name: %s' % (modlast) in cmd.stdout_text
def test_enabled_tls_protocols(self):
"""Check that only TLS 1.2 is enabled in Apache.
"""Check Apache has same TLS versions enabled as crypto policy
This is the regression test for issue
https://pagure.io/freeipa/issue/7995.
@@ -698,9 +698,24 @@ class TestIPACommand(IntegrationTest):
)
return res.returncode == 0
# get minimum version from current crypto-policy
openssl_cnf = self.master.get_file_contents(
"/etc/crypto-policies/back-ends/opensslcnf.config",
encoding="utf-8"
)
mo = re.search(r"MinProtocol\s*=\s*(TLSv[0-9.]+)", openssl_cnf)
assert mo
min_tls = mo.group(1)
# Fedora DEFAULT has TLS 1.0 enabled, NEXT has TLS 1.2
# even FUTURE crypto policy has TLS 1.2 as minimum version
assert min_tls in {"TLSv1", "TLSv1.2"}
# On Fedora FreeIPA still disables TLS 1.0 and 1.1 in ssl.conf.
assert not is_tls_version_enabled('tls1')
assert not is_tls_version_enabled('tls1_1')
assert is_tls_version_enabled('tls1_2')
assert is_tls_version_enabled('tls1_3')
def test_samba_config_file(self):
"""Check that ipa-adtrust-install generates sane smb.conf

View File

@@ -5,11 +5,15 @@
"""
import os
import ssl
from unittest import mock
import pytest
from ipalib.util import get_pager
from ipalib.util import (
get_pager, create_https_connection, get_proper_tls_version_span
)
from ipaplatform.constants import constants
@pytest.mark.parametrize('pager,expected_result', [
@@ -24,3 +28,47 @@ def test_get_pager(pager, expected_result):
with mock.patch.dict(os.environ, {'PAGER': pager}):
pager = get_pager()
assert(pager == expected_result or pager.endswith(expected_result))
BASE_CTX = ssl.SSLContext(ssl.PROTOCOL_TLS)
if constants.TLS_HIGH_CIPHERS is not None:
BASE_CTX.set_ciphers(constants.TLS_HIGH_CIPHERS)
else:
BASE_CTX.set_ciphers("PROFILE=SYSTEM")
# options: IPA still supports Python 3.6 without min/max version setters
BASE_OPT = BASE_CTX.options
BASE_OPT |= (
ssl.OP_ALL | ssl.OP_NO_COMPRESSION | ssl.OP_SINGLE_DH_USE |
ssl.OP_SINGLE_ECDH_USE
)
TLS_OPT = (
ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 |
ssl.OP_NO_TLSv1_1
)
OP_NO_TLSv1_3 = getattr(ssl, "OP_NO_TLSv1_3", 0) # make pylint happy
@pytest.mark.parametrize('minver,maxver,opt,expected', [
(None, None, BASE_OPT, None),
(None, "tls1.3", BASE_OPT | TLS_OPT, ["tls1.2", "tls1.3"]),
("tls1.2", "tls1.3", BASE_OPT | TLS_OPT, ["tls1.2", "tls1.3"]),
("tls1.2", None, BASE_OPT | TLS_OPT, ["tls1.2", "tls1.3"]),
("tls1.2", "tls1.2", BASE_OPT | TLS_OPT | OP_NO_TLSv1_3, ["tls1.2"]),
(None, "tls1.2", BASE_OPT | TLS_OPT | OP_NO_TLSv1_3, ["tls1.2"]),
("tls1.3", "tls1.3", BASE_OPT | TLS_OPT | ssl.OP_NO_TLSv1_2, ["tls1.3"]),
("tls1.3", None, BASE_OPT | TLS_OPT | ssl.OP_NO_TLSv1_2, ["tls1.3"]),
])
def test_tls_version_span(minver, maxver, opt, expected):
assert get_proper_tls_version_span(minver, maxver) == expected
# file must exist and contain certs
cafile = ssl.get_default_verify_paths().cafile
conn = create_https_connection(
"invalid.test",
cafile=cafile,
tls_version_min=minver,
tls_version_max=maxver
)
ctx = getattr(conn, "_context")
assert ctx.options == BASE_OPT | opt
assert ctx.get_ciphers() == BASE_CTX.get_ciphers()