The unified diff between revisions [13065dec..] and [98cca741..] is displayed below. It can also be downloaded as a raw diff.

#
#
# add_file "policy.py"
#  content [fec54191bced3e6c8fcccaaf40868a0d019a5599]
#
# patch "addrhash.py"
#  from [86b3852b1b32d5902b03ae26bf9f0d1c86556fe5]
#    to [e337a3b9a2b6b89e5e8fa50962021781328339cc]
#
#   set "policy.py"
#  attr "mtn:execute"
# value "true"
#
============================================================
--- policy.py	fec54191bced3e6c8fcccaaf40868a0d019a5599
+++ policy.py	fec54191bced3e6c8fcccaaf40868a0d019a5599
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+from Crypto.Hash import MD5
+import addrhash
+import config
+import rfc822
+import sys
+
+if __name__ == '__main__':
+    # verify incoming email addresses; see if they're
+    # trying to brute-force us, and log that. otherwise,
+    # let the mail through and we'll log more about the
+    # message on delivery to that script
+
+    def check(req):
+        if not req.has_key('recipient'):
+            return "DUNNO"
+        try:
+            user = req['recipient']
+            user_at = user.find('@')
+            if user_at == -1:
+                return "DUNNO"
+            user = user[:user_at]
+            addrhash.decode(user)
+        except addrhash.GaisdeException, e:
+            return "REJECT 450 User unknown."
+
+        return "PREPEND X-Gaisde: HMAC-verified"
+
+    req = {}
+    while True:
+        line = sys.stdin.readline()
+        if line == '':
+            break
+        line = line.strip()
+        if not line:
+            try: response = check(req)
+            except: response = "DUNNO"
+            print response
+            req = {}
+        else:
+            sp = line.split('=', 1)
+            if len(sp) != 2:
+                continue
+            req[sp[0]] = sp[1]
+
============================================================
--- addrhash.py	86b3852b1b32d5902b03ae26bf9f0d1c86556fe5
+++ addrhash.py	e337a3b9a2b6b89e5e8fa50962021781328339cc
@@ -7,6 +7,9 @@ import base64
 import socket
 import base64

+class GaisdeException(Exception):
+    pass
+
 def get_cipher():
     sha = SHA256.new()
     sha.update(config.aes_key)
@@ -32,7 +35,7 @@ def strip_hmac_and_verify(val):
 def strip_hmac_and_verify(val):
     their_mac, val = val[:12], val[12:]
     if their_mac != mac_value(val):
-        raise Exception("HMAC does not verify!")
+        raise GaisdeException("hmac")
     return val

 def encode(ip_string):
@@ -41,9 +44,12 @@ def decode(email_address):
     return base64.encodestring(enc).rstrip('\n').rstrip('==')

 def decode(email_address):
-    bytes = base64.decodestring(email_address + '==\n')
+    try:
+        bytes = base64.decodestring(email_address + '==\n')
+    except:
+        raise GaisdeException("base64")
     if len(bytes) != 16:
-        raise Exception("This is not a valid email address.")
+        raise GaisdeException("length")
     decoded = get_cipher().decrypt(bytes)
     decoded = strip_hmac_and_verify(decoded)
     return our_ntop(decoded)