aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Cgi/listinfo.py6
-rwxr-xr-xMailman/Cgi/subscribe.py6
-rwxr-xr-xMailman/Defaults.py.in8
-rwxr-xr-xMailman/MailList.py7
-rw-r--r--Mailman/Utils.py21
5 files changed, 41 insertions, 7 deletions
diff --git a/Mailman/Cgi/listinfo.py b/Mailman/Cgi/listinfo.py
index 78fda942..b55c263d 100644
--- a/Mailman/Cgi/listinfo.py
+++ b/Mailman/Cgi/listinfo.py
@@ -218,9 +218,9 @@ def list_listinfo(mlist, lang):
remote = remote.rsplit(':', 1)[0]
replacements['<mm-subscribe-form-start>'] += (
'<input type="hidden" name="sub_form_token" value="%s:%s">\n'
- % (now, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
- now +
- mlist.internal_name() +
+ % (now, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" +
+ now + ":" +
+ mlist.internal_name() + ":" +
remote
).hexdigest()
)
diff --git a/Mailman/Cgi/subscribe.py b/Mailman/Cgi/subscribe.py
index aefce493..b6527a2a 100755
--- a/Mailman/Cgi/subscribe.py
+++ b/Mailman/Cgi/subscribe.py
@@ -173,9 +173,9 @@ def process_form(mlist, doc, cgidata, lang):
except ValueError:
ftime = fhash = ''
then = 0
- token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
- ftime +
- mlist.internal_name() +
+ token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" +
+ ftime + ":" +
+ mlist.internal_name() + ":" +
remote1).hexdigest()
if ftime and now - then > mm_cfg.FORM_LIFETIME:
results.append(_('The form is too old. Please GET it again.'))
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in
index 4406a1f3..7a86f63c 100755
--- a/Mailman/Defaults.py.in
+++ b/Mailman/Defaults.py.in
@@ -142,9 +142,14 @@ RECAPTCHA_SECRET_KEY = None
# in the installation. This supplements the individual list's ban_list.
# For example, to ban xxx@aol.com and any @gmail.com address beginning with
# yyy, set
-# GLOBAL_BAN_LIST = ['xxx@aol.com', '^yyy.*@gmail\.com$']
+# GLOBAL_BAN_LIST = ['xxx@aol\.com', '^yyy.*@gmail\.com$']
GLOBAL_BAN_LIST = []
+# IF the following is set to Yes, and a web subscribe comes from an IPv4
+# address and the IP is listed in Spamhaus SBL, CSS or XBL, the subscription
+# will be blocked.
+BLOCK_SPAMHAUS_LISTED_IP_SUBSCRIBE = No
+
# Command that is used to convert text/html parts into plain text. This
# should output results to standard output. %(filename)s will contain the
# name of the temporary file that the program should operate on.
@@ -1746,6 +1751,7 @@ add_language('cs', _('Czech'), 'iso-8859-2', 'ltr')
add_language('da', _('Danish'), 'iso-8859-1', 'ltr')
add_language('de', _('German'), 'iso-8859-1', 'ltr')
add_language('en', _('English (USA)'), 'us-ascii', 'ltr')
+add_language('eo', _('Esperanto'), 'utf-8', 'ltr')
add_language('es', _('Spanish (Spain)'), 'iso-8859-1', 'ltr')
add_language('et', _('Estonian'), 'iso-8859-15', 'ltr')
add_language('eu', _('Euskara'), 'iso-8859-15', 'ltr') # Basque
diff --git a/Mailman/MailList.py b/Mailman/MailList.py
index 619c3206..fdc3802a 100755
--- a/Mailman/MailList.py
+++ b/Mailman/MailList.py
@@ -908,6 +908,13 @@ class MailList(HTMLFormatter, Deliverer, ListAdmin,
syslog('vette', '%s banned subscription: %s%s (matched: %s)',
realname, email, whence, pattern)
raise Errors.MembershipIsBanned, pattern
+ # See if this is from a spamhaus listed IP.
+ if remote and mm_cfg.BLOCK_SPAMHAUS_LISTED_IP_SUBSCRIBE:
+ if Utils.banned_ip(remote):
+ whence = ' from %s' % remote
+ syslog('vette', '%s banned subscription: %s%s (Spamhaus IP)',
+ realname, email, whence)
+ raise Errors.MembershipIsBanned, 'Spamhaus IP'
# Sanity check the digest flag
if digest and not self.digestable:
raise Errors.MMCantDigestError
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index fd6ac796..cdc82366 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -1495,3 +1495,24 @@ def xml_to_unicode(s, cset):
else:
return s
+def banned_ip(ip):
+ if not dns_resolver:
+ return False
+ parts = ip.split('.')
+ if len(parts) != 4:
+ return False
+ lookup = '{}.{}.{}.{}.zen.spamhaus.org'.format(parts[3],
+ parts[2],
+ parts[1],
+ parts[0])
+ resolver = dns.resolver.Resolver()
+ try:
+ ans = resolver.query(lookup, dns.rdatatype.A)
+ except DNSException:
+ return False
+ if not ans:
+ return False
+ text = ans.rrset.to_text()
+ if re.search(r'127\.0\.0\.[2-7]$', text, re.MULTILINE):
+ return True
+ return False