Unverified Commit 5595c9a5 authored by Isis Lovecruft's avatar Isis Lovecruft
Browse files

Add rudimentary (email_addr,gpg_key_fingerprint) whitelist feature.

This serves two purposes. It allows arbitrary whitelisting of certain email
addresses for testing purposes, and once #9332 is fully implemented, will
allow encrypted emails to be sent to these whitelisted addresses.

 * FIXES part of #9332.
parent 7b14664e
......@@ -15,11 +15,14 @@
# for details.
# :copyright: (c) 2007-2013 The Tor Project, Inc.
# (c) 2007-2013, all sentient entities within the AUTHORS file
# :version: 0.0.8
# :version: 0.0.9
#===============================================================================
#
# CHANGELOG:
# ~~~~~~~~~~
# Changes in version 0.0.9 - 2014-06-06
# * ADD EMAIL_WHITELIST setting.
#
# Changes in version 0.0.8 - 2014-05-14
# * CHANGE RECAPTCHA_PRIV_KEY to RECAPTCHA_SEC_KEY.
#
......@@ -305,6 +308,9 @@ EMAIL_DOMAIN_MAP = {"mail.google.com": "gmail.com",
EMAIL_DOMAIN_RULES = {'gmail.com': ["ignore_dots", "dkim"],
'yahoo.com': ["dkim"]}
# A mapping of whitelisted email addresses to GnuPG key fingerprints:
EMAIL_WHITELIST = {}
# If there are any IPs in this list, only allow incoming connections from
# those IPs.
EMAIL_RESTRICT_IPS = []
......
......@@ -433,15 +433,27 @@ class SMTPAutoresponder(smtp.SMTPClient):
if not addrHeader:
logging.warn("No Sender header on incoming mail.")
else:
client = None
try:
client = smtp.Address(addr.normalizeEmail(
normalized = addr.normalizeEmail(
addrHeader,
self.incoming.context.domainMap,
self.incoming.context.domainRules))
except (addr.UnsupportedDomain, addr.BadEmail,
smtp.AddressError) as error:
self.incoming.context.domainRules)
client = smtp.Address(normalized)
except (addr.UnsupportedDomain, addr.BadEmail) as error:
logging.warn(error)
else:
# Check if it was one of the whitelisted addresses, because
# then it would make sense that it couldn't be canonicalized:
try: client = smtp.Address(addrHeader)
except smtp.AddressError as error: pass
else:
if str(client) in self.incoming.context.whitelist.keys():
logging.debug("Email address was whitelisted: %s."
% str(client))
except smtp.AddressError as error:
logging.warn(error)
if client:
clients.append(client)
return clients
......@@ -594,6 +606,9 @@ class SMTPAutoresponder(smtp.SMTPClient):
return False
logging.debug("Canonicalizing client email domain...")
# Allow whitelisted addresses through the canonicalization check:
if str(client) in self.incoming.context.whitelist.keys():
canonicalFromEmail = client.domain
# The client's address was already checked to see if it came from a
# supported domain and is a valid email address in :meth:`getMailTo`,
# so we should just be able to re-extract the canonical domain safely
......@@ -606,6 +621,9 @@ class SMTPAutoresponder(smtp.SMTPClient):
# ``From:`` header should match:
if self.incoming.canonicalFromSMTP != canonicalFromEmail:
logging.error("SMTP/Email canonical domain mismatch!")
logging.debug("Canonical domain mismatch: %s != %s"
% (self.incoming.canonicalFromSMTP,
canonicalFromEmail))
return False
domainRules = self.incoming.context.domainRules.get(
......
......@@ -91,6 +91,7 @@ class MailServerContext(object):
self.domainRules = config.EMAIL_DOMAIN_RULES or {}
self.domainMap = config.EMAIL_DOMAIN_MAP or {}
self.canon = self.buildCanonicalDomainMap()
self.whitelist = config.EMAIL_WHITELIST or {}
self.gpgContext = getGPGContext(config)
......@@ -276,6 +277,14 @@ class SMTPIncomingDelivery(smtp.SMTP):
error.
"""
try:
if str(origin) in self.context.whitelist.keys():
logging.warn("Got SMTP 'MAIL FROM:' whitelisted address: %s."
% str(origin))
# We need to be certain later that when the fromCanonicalSMTP
# domain is checked again the email 'From:' canonical domain,
# that we allow whitelisted addresses through the check.
self.fromCanonicalSMTP = origin.domain
return origin
if ((origin.domain == self.context.hostname) or
(origin.domain == smtp.DNSNAME)):
self.fromCanonicalSMTP = origin.domain
......
......@@ -37,6 +37,7 @@ EMAIL_DOMAIN_RULES = {
'localhost': [],
}
EMAIL_DOMAINS = ["gmail.com", "example.com", "localhost"]
EMAIL_WHITELIST = {'white@list.ed': 'ABCD1234ABCD1234ABCD1234ABCD1234ABCD1234'}
EMAIL_USERNAME = "bridges"
EMAIL_SMTP_HOST = "127.0.0.1"
EMAIL_SMTP_PORT = 25
......@@ -54,6 +55,7 @@ EMAIL_GPG_SIGNING_KEY = %s
EMAIL_DOMAIN_MAP = %s
EMAIL_DOMAIN_RULES = %s
EMAIL_DOMAINS = %s
EMAIL_WHITELIST = %s
EMAIL_USERNAME = %s
EMAIL_SMTP_HOST = %s
EMAIL_SMTP_PORT = %s
......@@ -69,6 +71,7 @@ EMAIL_PORT = %s
repr(EMAIL_DOMAIN_MAP),
repr(EMAIL_DOMAIN_RULES),
repr(EMAIL_DOMAINS),
repr(EMAIL_WHITELIST),
repr(EMAIL_USERNAME),
repr(EMAIL_SMTP_HOST),
repr(EMAIL_SMTP_PORT),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment