mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-23 07:33:27 -06:00
EPN: Enable certificate validation and hostname checking
https://pagure.io/freeipa/issue/8579 Signed-off-by: Stanislav Levin <slev@altlinux.org> Reviewed-By: Rob Crittenden <rcritten@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
parent
977063a56e
commit
32aa1540f0
@ -29,6 +29,7 @@ import os
|
||||
import pwd
|
||||
import logging
|
||||
import smtplib
|
||||
import ssl
|
||||
import time
|
||||
|
||||
from collections import deque
|
||||
@ -205,6 +206,7 @@ class EPN(admintool.AdminTool):
|
||||
def __init__(self, options, args):
|
||||
super(EPN, self).__init__(options, args)
|
||||
self._conn = None
|
||||
self._ssl_context = None
|
||||
self._expiring_password_user_list = EPNUserList()
|
||||
self._ldap_data = []
|
||||
self._date_ranges = []
|
||||
@ -291,12 +293,15 @@ class EPN(admintool.AdminTool):
|
||||
logger.error("IPA client is not configured on this system.")
|
||||
raise admintool.ScriptError()
|
||||
|
||||
# tasks required privileges
|
||||
self._get_krb5_ticket()
|
||||
self._read_configuration()
|
||||
self._validate_configuration()
|
||||
self._parse_configuration()
|
||||
self._get_connection()
|
||||
self._read_ipa_configuration()
|
||||
self._create_ssl_context()
|
||||
|
||||
drop_privileges()
|
||||
if self.options.mailtest:
|
||||
self._gentestdata()
|
||||
@ -316,6 +321,7 @@ class EPN(admintool.AdminTool):
|
||||
smtp_timeout=api.env.smtp_timeout,
|
||||
smtp_username=api.env.smtp_user,
|
||||
smtp_password=api.env.smtp_password,
|
||||
ssl_context=self._ssl_context,
|
||||
x_mailer=self.command_name,
|
||||
msg_subtype=api.env.msg_subtype,
|
||||
msg_charset=api.env.msg_charset,
|
||||
@ -457,6 +463,14 @@ class EPN(admintool.AdminTool):
|
||||
|
||||
return self._conn
|
||||
|
||||
def _create_ssl_context(self):
|
||||
"""Create SSL context.
|
||||
This must be done before the dropping priviliges to allow
|
||||
read in the smtp client's certificate and private key if specified.
|
||||
"""
|
||||
if api.env.smtp_security.lower() in ("starttls", "ssl"):
|
||||
self._ssl_context = ssl.create_default_context()
|
||||
|
||||
def _fetch_data_from_ldap(self, date_range):
|
||||
"""Run a LDAP query to fetch a list of user entries whose passwords
|
||||
would expire in the near future. Store in self._ldap_data.
|
||||
@ -603,15 +617,15 @@ class MTAClient:
|
||||
smtp_timeout=60,
|
||||
smtp_username=None,
|
||||
smtp_password=None,
|
||||
ssl_context=None,
|
||||
):
|
||||
# We only support "none" (cleartext) for now.
|
||||
# Future values: "ssl", "starttls"
|
||||
self._security_protocol = security_protocol
|
||||
self._smtp_hostname = smtp_hostname
|
||||
self._smtp_port = smtp_port
|
||||
self._smtp_timeout = smtp_timeout
|
||||
self._username = smtp_username
|
||||
self._password = smtp_password
|
||||
self._ssl_context = ssl_context
|
||||
|
||||
# This should not be touched
|
||||
self._conn = None
|
||||
@ -664,6 +678,7 @@ class MTAClient:
|
||||
host=self._smtp_hostname,
|
||||
port=self._smtp_port,
|
||||
timeout=self._smtp_timeout,
|
||||
context=self._ssl_context,
|
||||
)
|
||||
except (socketerror, smtplib.SMTPException) as e:
|
||||
msg = \
|
||||
@ -687,7 +702,7 @@ class MTAClient:
|
||||
|
||||
if self._security_protocol.lower() == "starttls":
|
||||
try:
|
||||
self._conn.starttls()
|
||||
self._conn.starttls(context=self._ssl_context)
|
||||
self._conn.ehlo()
|
||||
except smtplib.SMTPException as e:
|
||||
raise RuntimeError(
|
||||
@ -743,6 +758,7 @@ class MailUserAgent:
|
||||
smtp_timeout=60,
|
||||
smtp_username=None,
|
||||
smtp_password=None,
|
||||
ssl_context=None,
|
||||
x_mailer=None,
|
||||
msg_subtype="plain",
|
||||
msg_charset="utf8",
|
||||
@ -766,6 +782,7 @@ class MailUserAgent:
|
||||
smtp_timeout=smtp_timeout,
|
||||
smtp_username=smtp_username,
|
||||
smtp_password=smtp_password,
|
||||
ssl_context=ssl_context,
|
||||
)
|
||||
|
||||
def cleanup(self):
|
||||
|
@ -37,6 +37,7 @@ from subprocess import CalledProcessError
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipatests.test_integration.base import IntegrationTest
|
||||
from ipatests.pytest_ipa.integration.firewall import Firewall
|
||||
from ipatests.pytest_ipa.integration import tasks
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -58,12 +59,14 @@ USER_EPN_CONF = DEFAULT_EPN_CONF + textwrap.dedent(
|
||||
|
||||
STARTTLS_EPN_CONF = USER_EPN_CONF + textwrap.dedent(
|
||||
"""\
|
||||
smtp_server={server}
|
||||
smtp_security=starttls
|
||||
"""
|
||||
)
|
||||
|
||||
SSL_EPN_CONF = USER_EPN_CONF + textwrap.dedent(
|
||||
"""\
|
||||
smtp_server={server}
|
||||
smtp_port=465
|
||||
smtp_security=ssl
|
||||
"""
|
||||
@ -125,6 +128,9 @@ def configure_postfix(host, realm):
|
||||
# disable procmail if exists, make use of default local(8) delivery agent
|
||||
postconf(host, "mailbox_command=")
|
||||
|
||||
# listen on all active interfaces
|
||||
postconf(host, "inet_interfaces = all")
|
||||
|
||||
host.run_command(["systemctl", "restart", "saslauthd"])
|
||||
|
||||
result = host.run_command(["postconf", "mydestination"])
|
||||
@ -264,6 +270,7 @@ class TestEPN(IntegrationTest):
|
||||
# doesn't know about.
|
||||
# - Adds a class variable, pkg, containing the package name of
|
||||
# the downloaded *ipa-client-epn rpm.
|
||||
hosts = [cls.master, cls.clients[0]]
|
||||
tasks.uninstall_packages(cls.clients[0],EPN_PKG)
|
||||
pkgdir = tasks.download_packages(cls.clients[0], EPN_PKG)
|
||||
pkg = cls.clients[0].run_command(r'ls -1 {}'.format(pkgdir))
|
||||
@ -273,20 +280,20 @@ class TestEPN(IntegrationTest):
|
||||
'/tmp'])
|
||||
cls.clients[0].run_command(r'rm -rf {}'.format(pkgdir))
|
||||
|
||||
tasks.install_packages(cls.master, EPN_PKG)
|
||||
tasks.install_packages(cls.master, ["postfix"])
|
||||
tasks.install_packages(cls.clients[0], EPN_PKG)
|
||||
tasks.install_packages(cls.clients[0], ["postfix"])
|
||||
for host in (cls.master, cls.clients[0]):
|
||||
for host in hosts:
|
||||
tasks.install_packages(host, EPN_PKG + ["postfix"])
|
||||
try:
|
||||
tasks.install_packages(host, ["cyrus-sasl"])
|
||||
except Exception:
|
||||
# the package is likely already installed
|
||||
pass
|
||||
|
||||
tasks.install_master(cls.master, setup_dns=True)
|
||||
tasks.install_client(cls.master, cls.clients[0])
|
||||
configure_postfix(cls.master, cls.master.domain.realm)
|
||||
configure_postfix(cls.clients[0], cls.master.domain.realm)
|
||||
for host in hosts:
|
||||
configure_postfix(host, cls.master.domain.realm)
|
||||
Firewall(host).enable_services(["smtp", "smtps"])
|
||||
|
||||
|
||||
@classmethod
|
||||
def uninstall(cls, mh):
|
||||
@ -356,6 +363,7 @@ class TestEPN(IntegrationTest):
|
||||
"""Configure postfix without starttls and test no auth happens
|
||||
"""
|
||||
epn_conf = STARTTLS_EPN_CONF.format(
|
||||
server=self.master.hostname,
|
||||
user=self.master.config.admin_name,
|
||||
password=self.master.config.admin_password,
|
||||
)
|
||||
@ -373,6 +381,7 @@ class TestEPN(IntegrationTest):
|
||||
"""Configure postfix without tls and test no auth happens
|
||||
"""
|
||||
epn_conf = SSL_EPN_CONF.format(
|
||||
server=self.master.hostname,
|
||||
user=self.master.config.admin_name,
|
||||
password=self.master.config.admin_password,
|
||||
)
|
||||
@ -681,6 +690,7 @@ class TestEPN(IntegrationTest):
|
||||
"""Configure with starttls and test delivery
|
||||
"""
|
||||
epn_conf = STARTTLS_EPN_CONF.format(
|
||||
server=self.master.hostname,
|
||||
user=self.master.config.admin_name,
|
||||
password=self.master.config.admin_password,
|
||||
)
|
||||
@ -696,6 +706,7 @@ class TestEPN(IntegrationTest):
|
||||
"""Configure with ssl and test delivery
|
||||
"""
|
||||
epn_conf = SSL_EPN_CONF.format(
|
||||
server=self.master.hostname,
|
||||
user=self.master.config.admin_name,
|
||||
password=self.master.config.admin_password,
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user