From 5b5e62e94894467973f0ca9d622dbbf1d2821d77 Mon Sep 17 00:00:00 2001 From: Jacob Appelbaum Date: Sun, 13 Jul 2008 17:21:57 +0000 Subject: [PATCH] Removal of gettor, it belongs in projects. svn:r15877 --- contrib/gettor/gettor.py | 141 ------------------ contrib/gettor/gettor_blacklist.py | 116 -------------- contrib/gettor/gettor_requests.py | 86 ----------- contrib/gettor/gettor_responses.py | 72 --------- .../negative-DKIM-header-package-sample.eml | 39 ----- .../sample-emails/negative-DKIM-header.eml | 39 ----- .../sample-emails/positive-DKIM-header.eml | 57 ------- 7 files changed, 550 deletions(-) delete mode 100755 contrib/gettor/gettor.py delete mode 100755 contrib/gettor/gettor_blacklist.py delete mode 100755 contrib/gettor/gettor_requests.py delete mode 100755 contrib/gettor/gettor_responses.py delete mode 100644 contrib/gettor/sample-emails/negative-DKIM-header-package-sample.eml delete mode 100644 contrib/gettor/sample-emails/negative-DKIM-header.eml delete mode 100644 contrib/gettor/sample-emails/positive-DKIM-header.eml diff --git a/contrib/gettor/gettor.py b/contrib/gettor/gettor.py deleted file mode 100755 index c687665a2f..0000000000 --- a/contrib/gettor/gettor.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/python2.5 -# -*- coding: utf-8 -*- -""" - - gettor.py by Jacob Appelbaum - This program will hand out Tor via email to supported systems. - This program is Free Software released under the GPLv3. - - It is intended to be used in a .forward file as part of a pipe like so: - - cat <<'EOF'> .forward - |/usr/local/bin/gettor.py - EOF - - You should have a dist/current/ mirror in a directory that gettor can read. - Such a mirror can be created like so: - - cd /usr/local/ - rsync -av rsync://rsync.torproject.org/tor/dist/current tor-dist-current/ - - You can keep it updated with a cronjob like so: - - MirrorDir=/usr/local/tor-dist-current/ - 0 3 * * * rsync -a rsync://rsync.torproject.org/tor/dist/current/ $MirrorDir - - You should ensure that for each file and signature pair you wish to - distribute, you have created a zip file containing both. - - While this program isn't written in a threaded manner per se, it is designed to function - as if it will be called as a pipe many times at once. There is a slight - desynchronization with blacklist entry checking and may result in false - negatives. This isn't perfect but it is designed to be lightweight. It could - be fixed easily with a shared locking system but this isn't implemented yet. - -""" - -__program__ = 'gettor.py' -__version__ = '20080713.00' -__url__ = 'https://tor-svn.freehaven.net/svn/tor/trunk/contrib/gettor/' -__author__ = 'Jacob Appelbaum ' -__copyright__ = 'Copyright (c) 2008, Jacob Appelbaum' -__license__ = 'See LICENSE for licensing information' - -try: - from future import antigravity -except ImportError: - antigravity = None - -import syslog -import gettor_blacklist -import gettor_requests -import gettor_responses - -if __name__ == "__main__": - - rawMessage = gettor_requests.getMessage() - parsedMessage = gettor_requests.parseMessage(rawMessage) - - if not parsedMessage: - syslog.syslog("gettor: No parsed message. Dropping message.") - print "gettor: No parsed message. Dropping message." - exit(1) - - signature = False - signature = gettor_requests.verifySignature(rawMessage) - print "Signature is : " + str(signature) - replyTo = False - srcEmail = "gettor@torproject.org" - - # TODO XXX: - # Make the zip files and ensure they match packageList - # Make each zip file like so: - # zip -9 windows-bindle.z \ - # vidalia-bundle-0.2.0.29-rc-0.1.6.exe \ - # vidalia-bundle-0.2.0.29-rc-0.1.6.exe.asc - # - packageList = { - "windows-bundle": "/tmp/windows-bundle.z", - "macosx-bundle": "/tmp/macosx-bundle.z", - "linux-bundle": "/tmp/linux-bundle.z", - "source-bundle": "/tmp/source-bundle.z" - } - - # XXX TODO: Ensure we have a proper replyTO or bail out (majorly malformed mail). - replyTo = gettor_requests.parseReply(parsedMessage) - - if not signature: - # Check to see if we've helped them to understand that they need DKIM in the past - previouslyHelped = gettor_blacklist.blackList(replyTo) - - if not replyTo: - syslog.syslog("No help dispatched. Invalid reply address for user.") - print "No help dispatched. Invalid reply address for user." - exit(1) - - if not signature and previouslyHelped: - syslog.syslog("gettor: Unsigned messaged to gettor by blacklisted user dropped.") - print "No help dispatched. Unsigned and unhelped for blacklisted user." - exit(1) - - if not signature and not previouslyHelped: - # Reply with some help and bail out - # Someday call blackList(replyTo) - message = """ - You should try your request again with a provider that implements DKIM. Sorry. - """ - gettor_responses.sendHelp(message, srcEmail, replyTo) - print "attempting to send email from: " + srcEmail + "The mail is sent to: " + replyTo - syslog.syslog("gettor: Unsigned messaged to gettor. We issued some help about using DKIM.") - print "gettor: Unsigned messaged to gettor. We issued some help about using DKIM." - exit(0) - - if signature: - syslog.syslog("gettor: Signed messaged to gettor.") - print "gettor: Signed messaged to gettor." - - try: - print "gettor: Parsing now." - package = gettor_requests.parseRequest(parsedMessage, packageList) - except: - package = None - - if package == "windows-bundle": - print "gettor: " + package + " selected." - syslog.syslog("gettor: " + package + " selected.") - message = "Here's your requested software as a zip file. Please \ - verify the signature." - print "attempting to send email from: " + - srcEmail + "The mail is sent to: " + replyTo - gettor_responses.sendPackage(message, srcEmail, replyTo, packageList[package]) - exit(0) - else: - print "Package request is unknown: " + package - message = " Your request was misunderstood. Please select one of the \ - following packages: " + packageList.keys() - - gettor_responses.sendHelp(message, srcEmail, replyTo) - print "attempting to send email from: " + srcEmail + "The mail is sent to: " + replyTo - syslog.syslog("gettor: Signed messaged to gettor. We issued some help about proper email formatting.") - print "gettor: Signed messaged to gettor. We issued some help about proper email formatting." - exit(0) diff --git a/contrib/gettor/gettor_blacklist.py b/contrib/gettor/gettor_blacklist.py deleted file mode 100755 index f31327ead3..0000000000 --- a/contrib/gettor/gettor_blacklist.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/python2.5 -""" -This library implements all of the black listing features needed for gettor. -""" - -import hashlib -import os - -stateDir = "/tmp/gettor/" -blStateDir = stateDir + "bl/" - -def blackList(address, createEntry=False): - """ - Check to see if an address is on our blacklist. If it is - we'll return true. - If requested, we'll attempt to create a blacklist entry and return true if - everything works out. - """ - # XXX TODO: Eventually we may want to sort entries with netcom - # style /tmp/gettor/2-digits-of-hash/2-more-digits/rest-of-hash files - - privateAddress = makeAddressPrivate(address) - blackListed = lookupBlackListEntry(privateAddress) - - if blackListed: - return True - elif createEntry: - return createBlackListEntry(privateAddress) - - return False - -def lookupBlackListEntry(privateAddress, stateDir="/tmp/gettor/bl/"): - """ Check to see if we have a blacklist entry for the given address. """ - entry = stateDir + str(privateAddress) - try: - entry = os.stat(entry) - except OSError: - return False - return True - -def createBlackListEntry(privateAddress, stateDir="/tmp/gettor/bl/"): - """ Create a zero byte file that represents the address in our blacklist. """ - entry = stateDir + str(privateAddress) - stat = None - try: - stat = os.stat(entry) - except OSError: - try: - fd = open(entry, 'w') - fd.close() - return True - except: - print "Entry not found. We were unable to create an entry." - return False - print "It appears that we already had an entry." - return False - -def removeBlackListEntry(privateAddress, stateDir="/tmp/gettor/bl/"): - """ Remove the zero byte file that represents an entry in our blacklist.""" - entry = stateDir + str(privateAddress) - stat = None - try: - entry = os.unlink(entry) - except OSError: - return False - return True - -def makeAddressPrivate(address): - """ Creates a unique identifier for the user. """ - hash = hashlib.sha1(address) - privateAddress = hash.hexdigest() - return privateAddress - -def prepBLStateDir(stateDir = "/tmp/gettor/bl/"): - print "Preparing the state directory for gettor." - stat = None - try: - stat = os.stat(stateDir) - print "We found a state directory" - return True - except OSError: - try: - os.mkdir(stateDir) - print "No state directory was found, we created one" - return True - except: - print "Unable to make a state directory" - return False - -def blackListtests(address): - """ This is a basic evaluation of our blacklist functionality """ - prepBLStateDir() - privateAddress = makeAddressPrivate(address) - print "We have a private address of: " + privateAddress - print "Testing creation of blacklist entry: " - blackListEntry = createBlackListEntry(privateAddress) - print blackListEntry - print "We're testing a lookup of a known positive blacklist entry: " - blackListEntry = lookupBlackListEntry(privateAddress) - print blackListEntry - print "We're testing removal of a known blacklist entry: " - blackListEntry = removeBlackListEntry(privateAddress) - print blackListEntry - print "We're testing a lookup of a known false blacklist entry: " - blackListEntry = lookupBlackListEntry(privateAddress) - print blackListEntry - print "Now we'll test the higher level blacklist functionality..." - print "This should not find an entry in the blacklist: " - print blackList(address) - print "This should add an entry to the blacklist: " - print blackList(address, True) - print "This should find the previous addition to the blacklist: " - print blackList(address) - print "Please ensure the tests match what you would expect for your environment." - -if __name__ == "__main__" : - blackListtests("requestingUser@example.com") diff --git a/contrib/gettor/gettor_requests.py b/contrib/gettor/gettor_requests.py deleted file mode 100755 index 06df1c5424..0000000000 --- a/contrib/gettor/gettor_requests.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/python2.5 -# -*- coding: utf-8 -*- -""" -This library implements all of the email parsing features needed for gettor. -""" - -import sys -import email -import dkim -import re - -def getMessage(): - """ Read the message into a buffer and return it """ - rawMessage = sys.stdin.read() - return rawMessage - -def verifySignature(rawMessage): - """ Attempt to verify the DKIM signature of a message and return a positive or negative status """ - signature = False - - # TODO XXX: - # This should catch DNS exceptions and fail to verify if we have a - # dns timeout - if dkim.verify(rawMessage): - signature = True - return signature - else: - return signature - -def parseMessage(message): - """ parse an email message and return a parsed email object """ - return email.message_from_string(message) - -def parseReply(parsedMessage): - """ Return an email address that we want to email """ - # TODO XXX: - # Scrub this data - address = parsedMessage["from"] - return address - -def parseRequest(parsedMessage, packages): - """ This parses the request and returns the first specific package name for - sending. If we do not understand the request, we return None as the package - name.""" - # XXX TODO: - # Should we pick only the first line of the email body. Drop the rest? - # It may be too unfriendly to our users - for line in email.Iterators.body_line_iterator(parsedMessage): - for package in packages.keys(): - print "Line is: " + line - print "Package is " + package - match = re.match(package, line) - if match: - return package - # If we get here, we didn't find a package we're currently serving - return None - -if __name__ == "__main__" : - """ Give us an email to understand what we think of it. """ - packageList = { - "windows-bundle": "/tmp/windows-bundle.z", - "macosx-bundle": "/tmp/macosx-bundle.z", - "linux-bundle": "/tmp/linux-bundle.z", - "source-bundle": "/tmp/source-bundle.z" - } - - print "Fetching raw message." - rawMessage = getMessage() - # This doesn't work without DNS ( no wifi on board current airplane ) - print "Verifying signature of message." - signature = verifySignature(rawMessage) - print "Parsing Message." - parsedMessage = parseMessage(rawMessage) - print "Parsing reply." - parsedReply = parseReply(parsedMessage) - print "Parsing package request." - package = parseRequest(parsedMessage, packageList) - if package == None: - package = "help" - else: - package = packageList[package] - - print "The signature status of the email is: " + str(signature) - print "The email requested the following reply address: " + parsedReply - print "It looks like the email requested the following package: " + package - print "We would select the following package file: " + package diff --git a/contrib/gettor/gettor_responses.py b/contrib/gettor/gettor_responses.py deleted file mode 100755 index 4e6ba80ba0..0000000000 --- a/contrib/gettor/gettor_responses.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python2.5 -# -*- coding: utf-8 -*- -""" This library implements all of the email replying features needed for gettor. """ - -import smtplib -import MimeWriter -import syslog -import StringIO -import base64 - -def sendHelp(message, source, destination): - """ Send a helpful message to the user interacting with us """ - help = constructMessage(message, source, destination) - try: - print "Attempting to send the following message: " - status = sendMessage(help, source, destination) - except: - print "Message sending failed." - status = False - return status - -def sendPackage(message, source, destination, filelist): - """ Send a message with an attachment to the user interacting with us """ - package = constructMessage(message, source, destination, filelist) - try: - print "Attempting to send the following message: " - status = sendMessage(package, destination) - except: - print "Message sending failed." - status = False - return status - -def constructMessage(messageText, ourAddress, recipient, fileList=None, fileName="requested-files.z"): - """ Construct a multi-part mime message, including only the first part - with plaintext.""" - - message = StringIO.StringIO() - mime = MimeWriter.MimeWriter(message) - mime.addheader('MIME-Version', '1.0') - mime.addheader('Subject', 'Your request has been processed') - mime.addheader('To', recipient) - mime.addheader('From', ourAddress) - mime.startmultipartbody('mixed') - - firstPart = mime.nextpart() - emailBody = firstPart.startbody('text/plain') - emailBody.write(messageText) - - # Add a file if we have one - if fileList: - # XXX TODO: Iterate over each file eventually - filePart = mime.nextpart() - filePart.addheader('Content-Transfer-Encoding', 'base64') - emailBody = filePart.startbody('application/zip; name=%s' % fileName) - base64.encode(open(fileList, 'rb'), emailBody) - - # Now end the mime messsage - mime.lastpart() - return message - -def sendMessage(message, dst, src="gettor@torproject.org", smtpserver="localhost:2700"): - try: - smtp = smtplib.SMTP(smtpserver) - smtp.sendmail(src, dst, message.getvalue()) - smtp.quit() - status = True - except: - return False - - return status - - diff --git a/contrib/gettor/sample-emails/negative-DKIM-header-package-sample.eml b/contrib/gettor/sample-emails/negative-DKIM-header-package-sample.eml deleted file mode 100644 index ac113e88b0..0000000000 --- a/contrib/gettor/sample-emails/negative-DKIM-header-package-sample.eml +++ /dev/null @@ -1,39 +0,0 @@ -X-Account-Key: account6 -X-UIDL: 1215752284.31537.faustus,S=1469 -X-Mozilla-Status: 0001 -X-Mozilla-Status2: 02000000 -Return-Path: -Delivered-To: jpopped@appelbaum.net -Received: (qmail 31535 invoked by uid 89); 11 Jul 2008 04:58:04 -0000 -Delivered-To: appelbaum.net-jacob@appelbaum.net -Received: (qmail 31531 invoked by uid 89); 11 Jul 2008 04:58:04 -0000 -Received: from unknown (HELO moria.seul.org) (128.31.0.34) - by 0 with (DHE-RSA-AES256-SHA encrypted) SMTP; 11 Jul 2008 04:58:04 -0000 -Received-SPF: none (0: domain at appelbaum.net does not designate permitted sender hosts) -Received: by moria.seul.org (Postfix) - id F09581415CD3; Fri, 11 Jul 2008 00:55:45 -0400 (EDT) -Delivered-To: gettor@seul.org -Received: from mail.lostinthenoise.net (mail.lostinthenoise.net [64.142.98.226]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (No client certificate requested) - by moria.seul.org (Postfix) with ESMTP id C464A140F476 - for ; Fri, 11 Jul 2008 00:55:45 -0400 (EDT) -Received: (qmail 31524 invoked by uid 89); 11 Jul 2008 04:58:02 -0000 -Received: from unknown (HELO ?127.0.0.1?) (64.142.98.226) - by 0 with (DHE-RSA-AES256-SHA encrypted) SMTP; 11 Jul 2008 04:58:02 -0000 -Message-ID: <4876E7D0.5050201@appelbaum.net> -Date: Thu, 10 Jul 2008 21:55:44 -0700 -From: Jacob Appelbaum -User-Agent: Icedove 1.5.0.14eol (X11/20080509) -MIME-Version: 1.0 -To: gettor@torproject.org -Subject: negative DKIM signature -X-Enigmail-Version: 0.94.2.0 -OpenPGP: id=9D0FACE4; - url=http://www.appelbaum.net/gpg.asc -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit - -source-bundle - - diff --git a/contrib/gettor/sample-emails/negative-DKIM-header.eml b/contrib/gettor/sample-emails/negative-DKIM-header.eml deleted file mode 100644 index 543d695e2a..0000000000 --- a/contrib/gettor/sample-emails/negative-DKIM-header.eml +++ /dev/null @@ -1,39 +0,0 @@ -X-Account-Key: account6 -X-UIDL: 1215752284.31537.faustus,S=1469 -X-Mozilla-Status: 0001 -X-Mozilla-Status2: 02000000 -Return-Path: -Delivered-To: jpopped@appelbaum.net -Received: (qmail 31535 invoked by uid 89); 11 Jul 2008 04:58:04 -0000 -Delivered-To: appelbaum.net-jacob@appelbaum.net -Received: (qmail 31531 invoked by uid 89); 11 Jul 2008 04:58:04 -0000 -Received: from unknown (HELO moria.seul.org) (128.31.0.34) - by 0 with (DHE-RSA-AES256-SHA encrypted) SMTP; 11 Jul 2008 04:58:04 -0000 -Received-SPF: none (0: domain at appelbaum.net does not designate permitted sender hosts) -Received: by moria.seul.org (Postfix) - id F09581415CD3; Fri, 11 Jul 2008 00:55:45 -0400 (EDT) -Delivered-To: gettor@seul.org -Received: from mail.lostinthenoise.net (mail.lostinthenoise.net [64.142.98.226]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (No client certificate requested) - by moria.seul.org (Postfix) with ESMTP id C464A140F476 - for ; Fri, 11 Jul 2008 00:55:45 -0400 (EDT) -Received: (qmail 31524 invoked by uid 89); 11 Jul 2008 04:58:02 -0000 -Received: from unknown (HELO ?127.0.0.1?) (64.142.98.226) - by 0 with (DHE-RSA-AES256-SHA encrypted) SMTP; 11 Jul 2008 04:58:02 -0000 -Message-ID: <4876E7D0.5050201@appelbaum.net> -Date: Thu, 10 Jul 2008 21:55:44 -0700 -From: Jacob Appelbaum -User-Agent: Icedove 1.5.0.14eol (X11/20080509) -MIME-Version: 1.0 -To: gettor@torproject.org -Subject: negative DKIM signature -X-Enigmail-Version: 0.94.2.0 -OpenPGP: id=9D0FACE4; - url=http://www.appelbaum.net/gpg.asc -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit - -testing - - diff --git a/contrib/gettor/sample-emails/positive-DKIM-header.eml b/contrib/gettor/sample-emails/positive-DKIM-header.eml deleted file mode 100644 index 6ada7d7572..0000000000 --- a/contrib/gettor/sample-emails/positive-DKIM-header.eml +++ /dev/null @@ -1,57 +0,0 @@ -X-Account-Key: account6 -X-UIDL: 1214981061.25808.faustus,S=2285 -X-Mozilla-Status: 0001 -X-Mozilla-Status2: 02000000 -Return-Path: -Delivered-To: jpopped@appelbaum.net -Received: (qmail 25806 invoked by uid 89); 2 Jul 2008 06:44:21 -0000 -Delivered-To: appelbaum.net-jacob@appelbaum.net -Received: (qmail 25804 invoked by uid 89); 2 Jul 2008 06:44:21 -0000 -Received: from unknown (HELO wa-out-1112.google.com) (209.85.146.180) - by 0 with SMTP; 2 Jul 2008 06:44:21 -0000 -Received-SPF: pass (0: SPF record at _spf.google.com designates 209.85.146.180 as permitted sender) -Received: by wa-out-1112.google.com with SMTP id j40so170432wah.1 - for ; Tue, 01 Jul 2008 23:42:01 -0700 (PDT) -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=gamma; - h=domainkey-signature:received:received:message-id:date:from:to - :subject:mime-version:content-type; - bh=IvFqNkffeoST7vamh2ytuq/b7GpLhg2hStTrQq3I3rE=; - b=xQR0hE/J4AXpAqH1UDXTtDrU9Izc6WM8vtFudRBzldWYyRx3Vvfh2I2Opu8+O6wbAv - jlDi18anUMbZqlIGSgGOxvXW4CltpX/SFZm1aGL4AisQ1Bi5xEqlrc8OnX3sA2xKeM3g - KWsWm+GVSMI4XAqnY9FYAfPx4DmOAfkdMyWCU= -DomainKey-Signature: a=rsa-sha1; c=nofws; - d=gmail.com; s=gamma; - h=message-id:date:from:to:subject:mime-version:content-type; - b=kyzDtGRDbiC5y4Bz/ylQjyHOChiOP2A6QDzybsVXc0C1hjHLImOQYR8gOxcRY+mRkN - 1xpBaEF4UloZAxTb79khRRp4TWmjT1DagtLx2MFzIj/F6awtdE/9U3p4QyKr8S43tGcE - ET26BSfT5u9zrXblVVAP3JedMPZ8mlIGQxyDs= -Received: by 10.115.90.1 with SMTP id s1mr6711509wal.51.1214980921268; - Tue, 01 Jul 2008 23:42:01 -0700 (PDT) -Received: by 10.114.184.16 with HTTP; Tue, 1 Jul 2008 23:41:57 -0700 (PDT) -Message-ID: <7fadd8130807012341n3b3af401mbdb4a29c80310bd3@mail.gmail.com> -Date: Tue, 1 Jul 2008 23:41:57 -0700 -From: "Jacob Applebaum" -To: jacob@appelbaum.net -Subject: Positive DKIM header -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_Part_462_28562233.1214980917793" - -------=_Part_462_28562233.1214980917793 -Content-Type: text/plain; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -This email should have a positive DKIM header. - -------=_Part_462_28562233.1214980917793 -Content-Type: text/html; charset=ISO-8859-1 -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -This email should have a positive DKIM header.
- -------=_Part_462_28562233.1214980917793-- - -