ldap-acl-milter/app/lam_config_backend.py

154 lines
6.3 KiB
Python

import re
import os
from lam_logger import log_info
from lam_exceptions import LamConfigBackendException
from lam_rex import g_rex_email
class LamConfigBackend():
def __init__(self):
self.milter_name = 'ldap-acl-milter'
self.milter_mode = 'test'
self.milter_socket = '/socket/{}'.format(self.milter_name)
self.milter_timeout = 60
self.milter_reject_message = 'Security policy violation!'
self.milter_tmpfail_message = 'Service temporarily not available! Please try again later.'
self.ldap_server = 'ldap://127.0.0.1:389'
self.ldap_server_connect_timeout = 3
self.ldap_binddn = 'cn=ldap-reader,ou=binds,dc=example,dc=org'
self.ldap_bindpw = 'TopSecret;-)'
self.ldap_base = 'ou=lam,ou=services,dc=example,dc=org'
self.ldap_query = '(&(mail=%rcpt%)(allowedEnvelopeSender=%from%))'
self.milter_schema = False
self.milter_schema_wildcard_domain = False
self.milter_expect_auth = False
self.milter_whitelisted_rcpts = {}
self.milter_dkim_enabled = False
self.milter_trusted_authservid = None
self.milter_max_rcpt_enabled = False
self.milter_max_rcpt = 1
if 'MILTER_NAME' in os.environ:
self.milter_name = os.environ['MILTER_NAME']
if 'MILTER_MODE' in os.environ:
if re.match(r'^test|reject$',os.environ['MILTER_MODE'], re.IGNORECASE):
self.milter_mode = os.environ['MILTER_MODE'].lower()
log_info("ENV[MILTER_MODE]: {}". format(self.milter_mode))
if 'MILTER_SOCKET' in os.environ:
self.milter_socket = os.environ['MILTER_SOCKET']
log_info("ENV[MILTER_SOCKET]: {}".format(self.milter_socket))
if 'MILTER_TIMEOUT' in os.environ:
if os.environ['MILTER_TIMEOUT'].isnumeric():
self.milter_timeout = int(os.environ['MILTER_TIMEOUT'])
else:
raise LamConfigBackendException("ENV[MILTER_TIMEOUT] must be numeric!")
log_info("ENV[MILTER_TIMEOUT]: {}".format(self.milter_timeout))
if 'MILTER_SCHEMA' in os.environ:
if re.match(r'^true$', os.environ['MILTER_SCHEMA'], re.IGNORECASE):
self.milter_schema = True
if 'MILTER_SCHEMA_WILDCARD_DOMAIN' in os.environ:
if re.match(r'^true$', os.environ['MILTER_SCHEMA_WILDCARD_DOMAIN'], re.IGNORECASE):
self.milter_schema_wildcard_domain = True
log_info("ENV[MILTER_SCHEMA]: {}".format(self.milter_schema))
log_info(
"ENV[MILTER_SCHEMA_WILDCARD_DOMAIN]: {}".format(
self.milter_schema_wildcard_domain
)
)
if 'LDAP_SERVER' not in os.environ:
raise LamConfigBackendException(
"Missing ENV[LDAP_SERVER], e.g. {}".format(self.ldap_server)
)
self.ldap_server = os.environ['LDAP_SERVER']
log_info("ENV[LDAP_SERVER]: {}".format(self.ldap_server))
if 'LDAP_SERVER_CONNECT_TIMEOUT' in os.environ:
if not os.environ['LDAP_SERVER_CONNECT_TIMEOUT'].isnumeric():
raise LamConfigBackendException(
"ENV[LDAP_SERVER_CONNECT_TIMEOUT] must be numeric!"
)
self.ldap_server_connect_timeout = int(os.environ['LDAP_SERVER_CONNECT_TIMEOUT'])
log_info("ENV[LDAP_SERVER_CONNECT_TIMEOUT]: {}".format(
self.ldap_server_connect_timeout
))
if 'LDAP_BINDDN' in os.environ:
self.ldap_binddn = os.environ['LDAP_BINDDN']
if 'LDAP_BINDPW' in os.environ:
self.ldap_bindpw = os.environ['LDAP_BINDPW']
if 'LDAP_BASE' not in os.environ:
raise LamConfigBackendException(
"Missing ENV[LDAP_BASE], e.g. {}".format(self.ldap_base)
)
self.ldap_base = os.environ['LDAP_BASE']
log_info("ENV[LDAP_BASE]: {}".format(self.ldap_base))
if 'LDAP_QUERY' not in os.environ:
if self.milter_schema == False:
raise LamConfigBackendException(
"ENV[MILTER_SCHEMA] is disabled and ENV[LDAP_QUERY] is not set instead!"
)
else:
self.ldap_query = os.environ['LDAP_QUERY']
log_info("ENV[LDAP_QUERY]: {}".format(self.ldap_query))
if 'MILTER_REJECT_MESSAGE' in os.environ:
self.milter_reject_message = os.environ['MILTER_REJECT_MESSAGE']
log_info("ENV[MILTER_REJECT_MESSAGE]: {}".format(self.milter_reject_message))
if 'MILTER_TMPFAIL_MESSAGE' in os.environ:
self.milter_tmpfail_message = os.environ['MILTER_TMPFAIL_MESSAGE']
log_info("ENV[MILTER_TMPFAIL_MESSAGE]: {}".format(self.milter_tmpfail_message))
if 'MILTER_EXPECT_AUTH' in os.environ:
if re.match(r'^true$', os.environ['MILTER_EXPECT_AUTH'], re.IGNORECASE):
self.milter_expect_auth = True
log_info("ENV[MILTER_EXPECT_AUTH]: {}".format(self.milter_expect_auth))
if 'MILTER_WHITELISTED_RCPTS' in os.environ:
# A blank separated list is expected
whitelisted_rcpts_str = os.environ['MILTER_WHITELISTED_RCPTS']
for whitelisted_rcpt in re.split(',|\s', whitelisted_rcpts_str):
if g_rex_email.match(whitelisted_rcpt) == None:
raise LamConfigBackendException(
"ENV[MILTER_WHITELISTED_RCPTS]: invalid email address: {}"
.format(whitelisted_rcpt)
)
else:
self.milter_whitelisted_rcpts[whitelisted_rcpt] = {}
log_info(
"ENV[MILTER_WHITELISTED_RCPTS]: {}".format(
self.milter_whitelisted_rcpts
)
)
if 'MILTER_DKIM_ENABLED' in os.environ:
self.milter_dkim_enabled = True
if 'MILTER_TRUSTED_AUTHSERVID' in os.environ:
self.milter_trusted_authservid = os.environ['MILTER_TRUSTED_AUTHSERVID'].lower()
log_info(
"ENV[MILTER_TRUSTED_AUTHSERVID]: {}".format(
self.milter_trusted_authservid
)
)
else:
raise LamConfigBackendException("ENV[MILTER_TRUSTED_AUTHSERVID] is mandatory!")
log_info("ENV[MILTER_DKIM_ENABLED]: {}".format(self.milter_dkim_enabled))
if 'MILTER_MAX_RCPT_ENABLED' in os.environ:
self.milter_max_rcpt_enabled = True
if 'MILTER_MAX_RCPT' in os.environ:
if os.environ['MILTER_MAX_RCPT'].isnumeric():
self.milter_max_rcpt = int(os.environ['MILTER_MAX_RCPT'])
log_info("ENV[MILTER_MAX_RCPT]: {}".format(self.milter_max_rcpt))
else:
raise LamConfigBackendException("ENV[MILTER_MAX_RCPT] must be numeric!")
log_info("ENV[MILTER_MAX_RCPT_ENABLED]: {}".format(self.milter_max_rcpt_enabled))