commit f1b7d03cf1e2dfbb9e11897d0bb07b43f5ad33e5 Author: Isis Lovecruft isis@torproject.org Date: Wed May 21 15:02:17 2014 +0000
Add unittest for MailMessage.getRecipient() which exposes 2.5 bugs.
Bug #1: ------- BridgeDB's current code will accept an incoming email with a 'To: givemebridges@serious.ly' header. However, BridgeDB's reply will still contain: 'From: bridges@torproject.org'
Obviously, it *shouldn't* be possible for any email whose SMTP RCPT TO domain is 'serious.ly' to actually end up in BridgeDB's mail queue. Though, if the outside SMTP layer is sent to '[bridges|ponticum].torproject.org' (with MAIL FROM a gmail/yahoo address), these messages still end up in BridgeDB's mail queue.
The following netcat session demonstrates that this is possible:
∃!isisⒶwintermute:(master *$=)~ ∴ torsocks nc bridges.torproject.org 25 220 ponticum.torproject.org ESMTP Postfix (Debian/GNU) HELO ponticum.torproject.org 250 ponticum.torproject.org MAIL FROM: isisgrimalkin@gmail.com 250 2.1.0 Ok RCPT TO: bridges@bridges.torproject.org 250 2.1.5 Ok DATA 354 End data with <CR><LF>.<CR><LF> From: isislovecruft@gmail.com To: givemebridgesrightnow@serious.ly Subject: mwhahaha
get transport obfs3 . 250 2.0.0 Ok: queued as F03972834F QUIT 221 2.0.0 Bye
This request resulted in the following debug logs: _______________________________________________________________________________ 15:30:31 DEBUG L690:server.validateFrom() ORIGIN: "'bridgedb@ponticum'" 15:30:31 DEBUG L699:server.validateFrom() Got canonical domain: 'ponticum' 15:30:31 DEBUG L495:server.lineReceived() > Received: from ponticum (ponticum [127.0.0.1]) for bridges@bridgedb; Wed, 21 May 2014 15:30:31 +0000 15:30:31 DEBUG L495:server.lineReceived() > From isisgrimalkin@gmail.com Wed May 21 15:30:31 2014 15:30:31 DEBUG L495:server.lineReceived() > X-Original-To: bridges@bridges.torproject.org 15:30:31 DEBUG L495:server.lineReceived() > Delivered-To: bridgedb@ponticum.torproject.org 15:30:31 DEBUG L495:server.lineReceived() > Received: from ponticum.torproject.org (kpebetka.net [95.79.25.182]) 15:30:31 DEBUG L495:server.lineReceived() > by ponticum.torproject.org (Postfix) with SMTP id F03972834F 15:30:31 DEBUG L495:server.lineReceived() > for bridges@bridges.torproject.org; Wed, 21 May 2014 15:29:18 +0000 (UTC) 15:30:31 DEBUG L495:server.lineReceived() > From: isislovecruft@gmail.com 15:30:31 DEBUG L495:server.lineReceived() > To: givemebridgesrightnow@serious.ly 15:30:31 DEBUG L495:server.lineReceived() > Subject: mwhahaha 15:30:31 DEBUG L495:server.lineReceived() > X-DKIM-Authentication-Results: dunno 15:30:31 DEBUG L495:server.lineReceived() > Date: Wed, 21 May 2014 15:30:31 -0000 15:30:31 DEBUG L495:server.lineReceived() > Message-Id: 1400686231.135135.6548@ponticum 15:30:31 DEBUG L495:server.lineReceived() > 15:30:31 DEBUG L495:server.lineReceived() > get transport obfs3 15:30:31 DEBUG L495:server.lineReceived() > 15:30:31 INFO L611:server.reply() Got an email; deciding whether to reply. 15:30:31 INFO L646:server.reply() Client requested email translation: en 15:30:31 DEBUG L70:request.determineBridg() Email request was valid. 15:30:31 DEBUG L160:request.withPluggableT() Parsing 'transport' line: 'get transport obfs3' 15:30:31 INFO L169:request.withPluggableT() Email requested transport type: 'obfs3' 15:30:31 DEBUG L81:request.determineBridg() Generating hashring filters for request. 15:30:31 INFO L420:Dist.getBridgesForEmai() Attempting to return for 3 bridges for isislovecruft@gmail.com... 15:30:31 DEBUG L445:Dist.getBridgesForEmai() Cache hit frozenset([<function filterBridgesByTransport(obfs3,<class 'ipaddr.IPv4Address'>)>]) 15:30:31 DEBUG L75:Dist.getNumBridgesPerA() Returning 3 bridges from ring of len: 492 15:30:31 DEBUG L1034:Bridges.getBridges() Got duplicate bridge 'edfa2fd66533da52f40424bbe917bd03c8378c2d' in main hashring for position 'eda7f69f7c08bd80861c3afa2921168a007d9ae5'. 15:30:31 DEBUG L1034:Bridges.getBridges() Got duplicate bridge 'ed0b2fd66f398afbf10424bb911790faca9ddb8e' in main hashring for position 'eda7f69f7c08bd80861c3afa2921168a007d9ae5'. 15:30:31 DEBUG L183:server.generateRespons() Email contents: From: bridges@torproject.org To: isislovecruft@gmail.com Message-ID: 20140521153031.21456.73227139.10726@ponticum.torproject.org In-Reply-To: 1400686231.135135.6548@ponticum Content-Type: text/plain; charset="utf-8" Date: Wed, 21 May 2014 15:30:31 +0000 Subject: Re: mwhahaha
Hey, isislovecruft!
[This is an automated message; please do not reply.]
Here are your bridges:
obfs3 10.1.1.1:1111 d14133856abbba8a65607baebf692162c567bf41 obfs3 10.2.2.2:2222 86f45ab5dcef80a4b1abfcc43579e76f1d0b25a4 obfs3 10.3.3.3:3333 5d55daabd91e041e74f62dcfab1a29c8bb32f0b2
To enter bridges into Tor Browser, follow the instructions on the Tor Browser download page [0] to start Tor Browser.
When the 'Tor Network Settings' dialogue pops up, click 'Configure' and follow the wizard until it asks:
> Does your Internet Service Provider (ISP) block or otherwise censor connections > to the Tor network?
Select 'Yes' and then click 'Next'. To configure your new bridges, copy and paste the bridge lines into the text input box. Finally, click 'Connect', and you should be good to go! If you experience trouble, try clicking the 'Help' button in the 'Tor Network Settings' wizard for further assistance.
[0]: https://www.torproject.org/projects/torbrowser.html.en#downloads-beta
COMMANDs: (combine COMMANDs to specify multiple options simultaneously) get bridges Request vanilla bridges. get transport [TYPE] Request a Pluggable Transport by TYPE. get help Displays this message. get key Get a copy of BridgeDB's public GnuPG key. get ipv6 Request IPv6 bridges.
Currently supported transport TYPEs: obfs2 obfs3 scramblesuit
-- <3 BridgeDB
---------------------------------------------------------------------- Public Keys: https://bridges.torproject.org/keys This email was generated with rainbows, unicorns, and sparkles for isislovecruft@gmail.com on Wednesday, 21 May, 2014 at 15:30:31.
15:30:31 INFO L655:server.reply() Sending reply to isislovecruft@gmail.com _______________________________________________________________________________
Which obviously brings us to the other bug.
Bug #2: ------- BridgeDB will accept an email from an arbitrary gmail/yahoo email address at the SMTP layer, and then send the reply to a *different* arbitrary gmail/yahoo email address taken from the contents of the email headers.
As you can see in the example above, the SMTP command 'MAIL FROM: isisgrimalkin@gmail.com' combined with a 'From: isislovecruft@gmail.com' in the email headers within the SMTP DATA segment caused the reply to be sent the reply to the later, when it came from the former. The person reading the response from BridgeDB also has no way to know who originally emailed BridgeDB to cause this email to end up in her inbox.
I'm not exactly certain if this is a bug or a feature. While it could be used for sending some junk to an arbitrary gmail/yahoo address, it could also be used as a sort of
"Dear BridgeDB, can I have some bridges? Asking for a friend."
mechanism.
Bug #2.5: --------- Also, "dunno" certainly isn't a valid DKIM signature. --- lib/bridgedb/test/test_email_server.py | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/lib/bridgedb/test/test_email_server.py b/lib/bridgedb/test/test_email_server.py index d7f2922..32c40ac 100644 --- a/lib/bridgedb/test/test_email_server.py +++ b/lib/bridgedb/test/test_email_server.py @@ -323,6 +323,17 @@ class MailMessageTests(unittest.TestCase): recipient = self.message.getRecipient(incoming) self.assertEqual(recipient, self.context.fromAddr)
+ def test_MailMessage_getRecipient_givemebridges_at_seriously(self): + """MailMessage.getRecipient() for an incoming email sent to any email + address other than the one we're listening for should return our + configured address, not the one in the incoming email. + """ + self._getIncomingLines() + self.message.lines[1] = 'To: givemebridges@serious.ly' + incoming = self.message.getIncomingMessage() + recipient = self.message.getRecipient(incoming) + self.assertEqual(recipient, self.context.fromAddr) + def test_MailMessage_getRecipient_bad_address(self): """MailMessage.getRecipient() for an incoming email sent to a malformed email address should log an smtp.AddressError and then return our
tor-commits@lists.torproject.org