import os import time import rfc822 import sha import popen2 import binascii import re fpr_re = re.compile ("^.+ingerprint: (.*)") uid_re = re.compile ("^\(([0-9]+)\)\.?[^<]*<([^>]*)>") key = "CHANGETHIS" def sign_key (keyid, uid): z = os.system ("~/local/bin/gpg --batch --yes --default-cert-check-level 2 -u 0x9C851DF1 --edit-key " + keyid + " \"uid " + str(uid) + "\" sign save"""); if (z != 0): return 1 return None def send_email (addr, str): (iout, iin) = popen2.popen2 ("/usr/lib/sendmail " + addr) print "email to " + addr iin.write ("""From: "Imperialviolet Key Verifier" Reply-To: keyverify@imperialviolet.org Subject: Key Verify Request To: """ + addr + """ """ + str); iin.close (); iout.close (); def send_download_failed_email (addr, keyid): send_email (addr, """This is from the key verification bot at Imperialviolet.org. This message was sent to: """+addr+""" Someone has requested that keyid """+keyid+""" be verified as being owned by the person controlling this email address. If you did not request this then please ignore this email I cannot download that key from wwwkeys.pgp.net. Please make sure you have uploaded your key with the HKP protocol to this server. The problem could be a connection issue at this end of course. Thank You (This is an automated bot. My owner can be reached at keyverifyowner@imperialviolet.org) """); def send_bad_uid_email (addr, keyid): send_email (addr, """This is from the key verification bot at Imperialviolet.org. This message was sent to: """+addr+""" Someone has requested that keyid """+keyid+""" be verified as being owned by the person controlling this email address. If you did not request this then please ignore this email I cannot find the correct uid in the key for your email address. Please check that a uid exists in the key with your exact email address as in the To header of this email Thank You (This is an automated bot. My owner can be reached at keyverifyowner@imperialviolet.org) """) def send_apply_reply_email (addr, keyid, magic, hash): send_email (addr, """This is from the key verification bot at Imperialviolet.org. This message was sent to: """+addr+""" Someone has requested that keyid """+keyid+""" be verified as being owned by the person controlling this email address. If you did not request this then DELETE THIS EMAIL NOW. Anyone who has access to this email can authenticate themselves as owning this address. If you wish to verify uid """+str(gpguid(keyid, addr))+""" of key """+keyid+""" with fingerprint """+fingerprint (keyid)+""" then reply to this email and SET THE SUBJECT to the following EXACTLY: (all on one line) CONFIRM """+keyid+ " " + magic + " " + hash + """ Thank You (This is an automated bot. My owner can be reached at keyverifyowner@imperialviolet.org) """) def send_failed_email (addr, keyid): send_email (addr, """This is from the key verification bot at Imperialviolet.org. This message was sent to: """+addr+""" Something went wrong while signing key """+keyid+""". Sorry. Try contacting my owner at keyverifyowner@imperialviolet.org """) def send_ok_email (addr, keyid): s = """This is from the key verification bot at Imperialviolet.org. This message was sent to: """+addr+""" Your key """+keyid+""" has been signed as requested and is attached below If you did not request this then someone else has access to your email and now has a key which certifies that they own it. In this case contact keyverifyowner@imperialviolet.org right away. Thank You """ (iout, iin) = popen2.popen2 ("~/local/bin/gpg -a --export " + keyid) l = iout.readline (); while (l != ""): s += l l = iout.readline () send_email (addr, s); def fingerprint (keyid): (iout, iin, ierr) = popen2.popen3 ("~/local/bin/gpg --batch --edit " + keyid + " fpr quit") l = ierr.readline (); while (l != ""): parts = fpr_re.split (l[:-1]) if (len (parts) == 3): return parts[1] l = ierr.readline () print "*** Fingerprint error" return None def gpguid (keyid, addr): (iout, iin, ierr) = popen2.popen3 ("~/local/bin/gpg --batch --edit " + keyid + " quit") l = ierr.readline (); while (l != ""): parts = uid_re.split (l[:-1]) if (len (parts) == 4): if (parts[2].lower() == addr.lower()): return int(parts[1]) l = ierr.readline () print "*** gpguid error" return None def process(name, fd): os.unlink ("mail/new/" + name) print name m = rfc822.Message (fd) subj = m.getfirstmatchingheader ("Subject") if (subj == None): return for i in range (len (subj)): subj[i] = re.sub ("^\s+", " ", subj[i][:-1]) subj = "".join(subj)[9:] print "Subject " + subj addr = m.getfirstmatchingheader ("From") if (addr == None): return if (len (addr) == 0): return addrlist = rfc822.AddressList (addr[0]) addr = addrlist[0][1] for c in addr: a = ord(c) if (a != ord('@') and a != ord ('_') and a != ord ('-') and a != ord ('.')): if ( (a < ord('0') or a > ord('9')) and (a < ord ('a') or a > ord ('z')) and (a < ord ('A') or a > ord ('Z'))): print "Failed on char " + c return #addr = "agl@localhost" print "From " + addr words = subj.split (' ') if (len(words) < 2): return words[0] = words[0].lower() words[1] = words[1].lower() for c in words[1]: a = ord('a') if (a < ord('0') or a > ord('9')): if (a < ord('a') or a > ord('f')): return print words if (words[0] == "apply"): if (len(words) != 2): return if (len (words[1]) >= 2 and words[1][1] == 'x'): words[1] = words[1][2:] if (len (words[1]) != 8): return # Get the GPG key z=os.system ("~/local/bin/gpg --recv-keys " + words[1]) z = 0 if (z != 0): send_download_failed_email (addr, words[1]) return if (gpguid (words[1], addr) == None): send_bad_uid_email (addr, words[1]) return fd = open ("/dev/random", "r") s = fd.read (20) p = binascii.b2a_base64 (s)[:-2] p.replace ("+", "a") p.replace ("/", "b") s = sha.new() s.update (addr) s.update (words[1]) s.update (p) s.update (key) send_apply_reply_email (addr, words[1], p, s.hexdigest()); return elif (words[0] == "confirm"): if (len(words) != 4): return s = sha.new () s.update (addr) s.update (words[1]) s.update (words[2]) s.update (key) if (s.hexdigest () != words[3]): return; if (sign_key (words[1], gpguid (words[1], addr)) != None): send_failed_email (addr, words[1]); return send_ok_email (addr, words[1]) if __name__ == "__main__": while 1: files = os.listdir ("mail/new") if (len(files) != 0): fd = open ("mail/new/" + files[0], "r") process (files[0], fd) fd.close (); time.sleep (1)