Changeset - c2f446ec7e2a
[Not reviewed]
0 5 0
Branko Majic (branko) - 4 years ago 2020-09-23 19:48:30
branko@majic.rs
MAR-158: Update default TLS ciphers configuration in the mail_server role:

- Updated the default value for parameter mail_server_tls_ciphers.
- Updated tests, making them explicitly test for enabled and disabled
ciphers.
- Refactored tests for TLS to use nmap ssl-enum-ciphers script for
listing available TLS versions and ciphers.
- Install nmap as part of preparation step.
- Updated role reference documentation.
5 files changed with 283 insertions and 134 deletions:
0 comments (0 inline, 0 general)
docs/rolereference.rst
Show inline comments
 
@@ -1118,7 +1118,7 @@ Parameters
 
  ``smtpd_tls_mandatory_protocols`` and Dovecot configuration option
 
  ``ssl_protocols``.
 

	
 
**mail_server_tls_ciphers** (string, optional ``DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!MD5:!EXPORT``)
 
**mail_server_tls_ciphers** (string, optional ``DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:!aNULL:!MD5:!EXPORT``)
 
  TLS ciphers to enable on the mail server (for IMAP and SMTP submission). This
 
  should be an OpenSSL-compatible cipher specification. Value should be
 
  compatible with Postfix configuration option ``tls_high_cipherlist`` and
roles/mail_server/defaults/main.yml
Show inline comments
 
@@ -10,7 +10,12 @@ local_mail_aliases: {}
 
imap_max_user_connections_per_ip: 10
 
mail_server_tls_protocols:
 
  - "TLSv1.2"
 
mail_server_tls_ciphers: "DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-GCM-SHA384:\
 
DHE-RSA-AES256-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-GCM-SHA384:\
 
ECDHE-RSA-AES256-SHA384:!aNULL:!MD5:!EXPORT"
 
mail_server_tls_ciphers: "\
 
DHE-RSA-AES128-GCM-SHA256:\
 
DHE-RSA-AES256-GCM-SHA384:\
 
DHE-RSA-CHACHA20-POLY1305:\
 
ECDHE-RSA-AES128-GCM-SHA256:\
 
ECDHE-RSA-AES256-GCM-SHA384:\
 
ECDHE-RSA-CHACHA20-POLY1305:\
 
!aNULL:!MD5:!EXPORT"
 
mail_message_size_limit: 10240000
roles/mail_server/molecule/default/prepare.yml
Show inline comments
 
@@ -61,7 +61,9 @@
 

	
 
    - name: Install tools for testing
 
      apt:
 
        name: gnutls-bin
 
        name:
 
          - gnutls-bin
 
          - nmap
 
        state: present
 

	
 
- hosts: stretch
roles/mail_server/molecule/default/tests/test_mandatory.py
Show inline comments
 
import os
 

	
 
import defusedxml.ElementTree as ElementTree
 

	
 
import pytest
 

	
 
import testinfra.utils.ansible_runner
 

	
 

	
 
@@ -106,12 +110,11 @@ def test_mail_owner(host):
 
    assert user.groups == ["vmail"]
 

	
 

	
 
def test_imap_tls_configuration(host):
 
def test_imap_tls_connectivity(host):
 
    """
 
    Tests TLS configuration for IMAP in Dovecot.
 
    Tests connectivity over STARTTLS/TLS towards IMAP server.
 
    """
 

	
 
    # Test plain connectivity first.
 
    starttls = host.run('echo "a0001 LOGOUT" | openssl s_client -quiet -starttls imap -connect parameters-mandatory:143')
 
    assert starttls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 
@@ -120,34 +123,50 @@ def test_imap_tls_configuration(host):
 
    assert tls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 

	
 
    # Test TLS protocol versions.
 
    starttls_old_tls_versions_disabled = host.run("echo 'a0001 LOGOUT' | openssl s_client -quiet -starttls imap -no_tls1_2 -connect parameters-mandatory:143")
 
    assert starttls_old_tls_versions_disabled.rc != 0
 
    assert "write:errno=104" in starttls_old_tls_versions_disabled.stderr or 'SSL alert number 70' in starttls_old_tls_versions_disabled.stderr
 

	
 
    tls_old_tls_versions_disabled = host.run("echo 'a0001 LOGOUT' | openssl s_client -quiet -no_tls1_2 -connect parameters-mandatory:993")
 
    assert tls_old_tls_versions_disabled.rc != 0
 
    assert "write:errno=104" in tls_old_tls_versions_disabled.stderr or 'SSL alert number 70' in tls_old_tls_versions_disabled.stderr
 
@pytest.mark.parametrize("port", [
 
    143,
 
    993,
 
    587,
 
])
 
def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port):
 
    """
 
    Tests if the correct TLS version and ciphers have been enabled for
 
    IMAP and SMTP submission.
 
    """
 

	
 
    expected_tls_versions = ["TLSv1.2"]
 

	
 
    expected_tls_ciphers = [
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
    ]
 

	
 
    # Test at least one strong TLS cipher.
 
    starttls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -starttls imap -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-mandatory:143")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p %s localhost -oX /tmp/report.xml", str(port))
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    tls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-mandatory:993")
 
    assert tls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in tls_cipher.stdout
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    # Test weaker TLS cipher are disabled.
 
    starttls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -starttls imap -cipher ECDHE-RSA-AES128-SHA -connect parameters-mandatory:143")
 
    assert starttls_cipher.rc != 0
 
    assert "CONNECTED" in starttls_cipher.stdout
 
    assert "ECDHE-RSA-AES128-SHA" not in starttls_cipher.stdout
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    tls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -cipher ECDHE-RSA-AES128-SHA -connect parameters-mandatory:993")
 
    assert tls_cipher.rc != 0
 
    assert "CONNECTED" in tls_cipher.stdout
 
    assert "ECDHE-RSA-AES128-SHA" not in tls_cipher.stdout
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_dovecot_postmaster(host):
 
@@ -175,51 +194,106 @@ def test_imap_max_user_connections_per_ip(host):
 
        assert "  mail_max_userip_connections = 10" in config.stdout
 

	
 

	
 
def test_postfix_tls_configuration(host):
 
def test_smtp_tls_connectivity(host):
 
    """
 
    Tests TLS configuration for SMTP in Postfix.
 
    Tests connectivity over default/submission port towards SMTP
 
    server.
 
    """
 

	
 
    # Test TLS protocol versions for default port (all should be enabled).
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1 -no_tls1_1 -connect parameters-mandatory:25")
 
    starttls = host.run('echo "QUIT" | openssl s_client -quiet -starttls smtp -connect parameters-mandatory:25')
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -connect parameters-mandatory:25")
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -no_tls1_1 -connect parameters-mandatory:25")
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    # Test TLS protocol versions for submission port (only TLS 1.2 should be enabled).
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -connect parameters-mandatory:587")
 
    assert starttls.rc == 0
 
    tls = host.run('echo "QUIT" | openssl s_client -quiet -starttls smtp -connect parameters-mandatory:587')
 
    assert tls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -connect parameters-mandatory:587")
 
    assert starttls.rc != 0
 
    assert 'write:errno=104' in starttls.stderr or 'SSL alert number 70' in starttls.stderr
 

	
 
    # Test ciphers for default port (less restrictive).
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-mandatory:25")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 

	
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA -connect parameters-mandatory:25")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA" in starttls_cipher.stdout
 

	
 
    # Test ciphers for submission port (weak ciphers not available).
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-mandatory:587")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 
def test_smtp_default_port_tls_version_and_ciphers(host):
 
    """
 
    Tests TLS configuration for SMTP default port (needs to be less
 
    restrictive for interoperability purposes).
 
    """
 

	
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA -connect parameters-mandatory:587")
 
    assert starttls_cipher.rc != 0
 
    assert "CONNECTED" in starttls_cipher.stdout
 
    assert "ECDHE-RSA-AES128-SHA" not in starttls_cipher.stdout
 
    expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
 

	
 
    expected_tls_ciphers = [
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_CCM",
 
        "TLS_DHE_RSA_WITH_AES_128_CCM_8",
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CCM",
 
        "TLS_DHE_RSA_WITH_AES_256_CCM_8",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_DHE_RSA_WITH_SEED_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_128_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
 
        "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
 
        "TLS_DH_anon_WITH_AES_256_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
 
        "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
 
        "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_DH_anon_WITH_SEED_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
 
        "TLS_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_RSA_WITH_AES_128_CCM",
 
        "TLS_RSA_WITH_AES_128_CCM_8",
 
        "TLS_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_RSA_WITH_AES_256_CCM",
 
        "TLS_RSA_WITH_AES_256_CCM_8",
 
        "TLS_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_RSA_WITH_SEED_CBC_SHA",
 
    ]
 

	
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p 25 localhost -oX /tmp/report.xml")
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_sieve_tls_configuration(host):
roles/mail_server/molecule/default/tests/test_optional.py
Show inline comments
 
@@ -3,6 +3,10 @@ import re
 
import time
 
import uuid
 

	
 
import defusedxml.ElementTree as ElementTree
 

	
 
import pytest
 

	
 
import testinfra.utils.ansible_runner
 

	
 

	
 
@@ -129,12 +133,11 @@ def test_mail_owner(host):
 
    assert user.groups == ["virtmail"]
 

	
 

	
 
def test_imap_tls_configuration(host):
 
def test_imap_tls_connectivity(host):
 
    """
 
    Tests TLS configuration for IMAP in Dovecot.
 
    Tests connectivity over STARTTLS/TLS towards IMAP server.
 
    """
 

	
 
    # Test plain connectivity first.
 
    starttls = host.run('echo "a0001 LOGOUT" | openssl s_client -quiet -starttls imap -connect parameters-optional:143')
 
    assert starttls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 
@@ -143,40 +146,53 @@ def test_imap_tls_configuration(host):
 
    assert tls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 

	
 
    # Test TLS protocol versions.
 
    starttls = host.run('echo "a0001 LOGOUT" | openssl s_client -quiet -starttls imap -no_tls1_2 -connect parameters-optional:143')
 
    assert starttls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 

	
 
    tls = host.run('echo "a0001 LOGOUT" | openssl s_client -quiet -no_tls1_2 -connect parameters-optional:993')
 
    assert tls.rc == 0
 
    assert '* BYE Logging out' in starttls.stdout
 
@pytest.mark.parametrize("port", [
 
    143,
 
    993,
 
    587,
 
])
 
def test_imap_and_smtp_submission_tls_version_and_ciphers(host, port):
 
    """
 
    Tests if the correct TLS version and ciphers have been enabled for
 
    IMAP and SMTP submission.
 
    """
 

	
 
    expected_tls_versions = ["TLSv1.1", "TLSv1.2"]
 

	
 
    expected_tls_ciphers = [
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
    ]
 

	
 
    starttls = host.run("echo 'a0001 LOGOUT' | openssl s_client -quiet -starttls imap -no_tls1_1 -no_tls1_2 -connect parameters-optional:143")
 
    assert starttls.rc != 0
 
    assert 'SSL alert number 70' in starttls.stderr
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p %s localhost -oX /tmp/report.xml", str(port))
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    tls = host.run("echo 'a0001 LOGOUT' | openssl s_client -quiet -no_tls1_1 -no_tls1_2 -connect parameters-optional:993")
 
    assert tls.rc != 0
 
    assert 'SSL alert number 70' in tls.stderr
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    # Test at least one strong TLS cipher.
 
    starttls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -starttls imap -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-optional:143")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    tls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-optional:993")
 
    assert tls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in tls_cipher.stdout
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    # Test weaker TLS cipher that was explicitly configured
 
    starttls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -starttls imap -cipher ECDHE-RSA-AES128-SHA -connect parameters-optional:143")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA" in starttls_cipher.stdout
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_cipher = host.run("echo 'a0001 LOGOUT' | openssl s_client -cipher ECDHE-RSA-AES128-SHA -connect parameters-optional:993")
 
    assert tls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA" in tls_cipher.stdout
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_dovecot_postmaster(host):
 
@@ -205,54 +221,106 @@ def test_imap_max_user_connections_per_ip(host):
 
        assert "  mail_max_userip_connections = 2" in config.stdout
 

	
 

	
 
def test_postfix_tls_configuration(host):
 
def test_smtp_tls_connectivity(host):
 
    """
 
    Tests TLS configuration for SMTP in Postfix.
 
    Tests connectivity over default/submission port towards SMTP
 
    server.
 
    """
 

	
 
    # Test TLS protocol versions for default port (all should be enabled).
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1 -no_tls1_1 -connect parameters-optional:25")
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -connect parameters-optional:25")
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -no_tls1_1 -connect parameters-optional:25")
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    # Test TLS protocol versions for submission port (only TLS 1.1 and TLS 1.2 should be enabled).
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -connect parameters-optional:587")
 
    starttls = host.run('echo "QUIT" | openssl s_client -quiet -starttls smtp -connect parameters-optional:25')
 
    assert starttls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_2 -connect parameters-optional:587")
 
    assert starttls.rc == 0
 
    tls = host.run('echo "QUIT" | openssl s_client -quiet -starttls smtp -connect parameters-optional:587')
 
    assert tls.rc == 0
 
    assert '221 2.0.0 Bye' in starttls.stdout
 

	
 
    starttls = host.run("echo 'QUIT' | openssl s_client -quiet -starttls smtp -no_tls1_1 -no_tls1_2 -connect parameters-optional:587")
 
    assert starttls.rc != 0
 
    assert 'SSL alert number 70' in starttls.stderr
 

	
 
    # Test ciphers for default port (less restrictive).
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-optional:25")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 

	
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA -connect parameters-optional:25")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA" in starttls_cipher.stdout
 

	
 
    # Test ciphers for submission port (at least one weak cipher was configured).
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA256 -connect parameters-optional:587")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA256" in starttls_cipher.stdout
 
def test_smtp_default_port_tls_version_and_ciphers(host):
 
    """
 
    Tests TLS configuration for SMTP default port (needs to be less
 
    restrictive for interoperability purposes).
 
    """
 

	
 
    starttls_cipher = host.run("echo 'QUIT' | openssl s_client -starttls smtp -cipher ECDHE-RSA-AES128-SHA -connect parameters-optional:587")
 
    assert starttls_cipher.rc == 0
 
    assert "ECDHE-RSA-AES128-SHA" in starttls_cipher.stdout
 
    expected_tls_versions = ["TLSv1.0", "TLSv1.1", "TLSv1.2"]
 

	
 
    expected_tls_ciphers = [
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_128_CCM",
 
        "TLS_DHE_RSA_WITH_AES_128_CCM_8",
 
        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_AES_256_CCM",
 
        "TLS_DHE_RSA_WITH_AES_256_CCM_8",
 
        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_DHE_RSA_WITH_SEED_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_128_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
 
        "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
 
        "TLS_DH_anon_WITH_AES_256_CBC_SHA",
 
        "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
 
        "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
 
        "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_DH_anon_WITH_SEED_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
 
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 
        "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
 
        "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
 
        "TLS_RSA_WITH_AES_128_CBC_SHA",
 
        "TLS_RSA_WITH_AES_128_CBC_SHA256",
 
        "TLS_RSA_WITH_AES_128_CCM",
 
        "TLS_RSA_WITH_AES_128_CCM_8",
 
        "TLS_RSA_WITH_AES_128_GCM_SHA256",
 
        "TLS_RSA_WITH_AES_256_CBC_SHA",
 
        "TLS_RSA_WITH_AES_256_CBC_SHA256",
 
        "TLS_RSA_WITH_AES_256_CCM",
 
        "TLS_RSA_WITH_AES_256_CCM_8",
 
        "TLS_RSA_WITH_AES_256_GCM_SHA384",
 
        "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
 
        "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
 
        "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
 
        "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
 
        "TLS_RSA_WITH_SEED_CBC_SHA",
 
    ]
 

	
 
    # Run the nmap scanner against the server, and fetch the results.
 
    nmap = host.run("nmap -sV --script ssl-enum-ciphers -p 25 localhost -oX /tmp/report.xml")
 
    assert nmap.rc == 0
 
    report_content = host.file('/tmp/report.xml').content_string
 

	
 
    report_root = ElementTree.fromstring(report_content)
 

	
 
    tls_versions = []
 
    tls_ciphers = set()
 

	
 
    for child in report_root.findall("./host/ports/port/script/table"):
 
        tls_versions.append(child.attrib['key'])
 

	
 
    for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"):
 
        tls_ciphers.add(child.text)
 

	
 
    tls_versions.sort()
 
    tls_ciphers = sorted(list(tls_ciphers))
 

	
 
    assert tls_versions == expected_tls_versions
 
    assert tls_ciphers == expected_tls_ciphers
 

	
 

	
 
def test_sieve_tls_configuration(host):
0 comments (0 inline, 0 general)