To protect users against attacks in which someone forges an e-mail message which appears to be sent by BridgeDB, but which contains malicious bridges intended to target a specific user, BridgeDB must start GPG-signing its outgoing e-mail messages.
BridgeDB must also include the address to which it sent a message in the GPG-signed text, and warn users that they should verify that BridgeDB messages are GPG-signed and that the e-mail address in the signed message matches the e-mail address which the user requested bridges with.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
BridgeDB should also include information about (1) why it is important users verify the signature of the email, and (2) how users can verify the signature (pointing to the short user manual should be fine).
Is it OK to use unprotected protected keyfile?
Is gpg clearsign fine here?
What sort of friendly and encouraging text do we want to include to inspire users to actually verify messages? And, if the instructions we link to are on www.tpo, and *.tpo is blocked, what now?
Using a GPG key with no passphrase is fine. (I assume the HTTPS certificate has no passphrase either.)
Is gpg clearsign fine here?
Yes.
What sort of friendly and encouraging text do we want to include to inspire users to actually verify messages?
This is the hard part -- I don't have that text written.
And, if the instructions we link to are on www.tpo, and *.tpo is blocked, what now?
The Tor Short User Manual is sent out by GetTor with every Tor package. Perhaps GetTor should also be able to send a copy of TSUM only, or perhaps BridgeDB should attach a copy of TSUM to its messages (or have an extra command to ask for one).
For my work with LEAP, I ended up auditing a bunch of the python GnuPG tools, and then fixing one of them. If help is still needed on this ticket, it is easy for me to do so.
aagbsn: Did your branch for this ever get merged into the main bridgedb? Would you like me to help by reviewing/testing, or by writing something using the library I´m maintaining?
Trac: Cc: aagbsn, kaner, mikeperry to aagbsn, kaner, mikeperry, isis@torproject.org
I think it will be beneficial if we reorganize/extend the verifying-signatures[0] page to include a section that describes how one verifies our signed mail, too. Assuming we do this, then we don't need to describe the various methods for doing this on the various OSs inline. We may still want to distribute the TSUM, but presently it does not describe everything we need, so it will similarly need to be updated/extended to say how to verify our sig. This maybe worthwhile though, for places where tpo is blocked.
With regard to the email message, I think we can add something like this:
Please consider verifying that this email was sent by the Tor Projectand that it has not changed since its creation. A malicious bridge candestroy your anonymity, so you may want to confirm that this email islegitimate and was not altered. You can follow the instructions at https://www.torproject.org/docs/verifying-signatures.html.en to verifythis email.If you don't need step-by-step instructions, then our public signingkey is also available athttps://bridges.torproject.org/sig and our fingerprint is [fpr]. Ifyou don't know how to use this information, then please go to the abovementioned website or contact help@rt.torproject.org for assistance.
(I dialed-back the scariness/pushiness of my original message) Suggestions?
Thus making:
-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA1[This is an automated message; please do not reply.]Here are your bridge relays: [bridges x 3]Bridge relays (or "bridges" for short) are Tor relays that aren't listedin the main directory. Since there is no complete public list of them,even if your ISP is filtering connections to all the known Tor relays,they probably won't be able to block all the bridges.To use the above lines, go to Vidalia's Network settings page, and click"My ISP blocks connections to the Tor network". Then add each bridgeaddress one at a time.Configuring more than one bridge address will make your Tor connectionmore stable, in case some of the bridges become unreachable.The following commands are also supported: ipv6 : request ipv6 bridges. transport NAME : request transport NAME. Example: 'transport obfs2'Another way to find public bridge addresses is to visithttps://bridges.torproject.org/. The answers you get from that pagewill change every few days, so check back periodically if you need morebridge addresses.Please consider verifying that this email was sent by the Tor Projectand that it has not changed since its creation. A malicious bridge candestroy your anonymity, so you may want to confirm that this email islegitimate and was not altered. You can follow the instructions at https://www.torproject.org/docs/verifying-signatures.html.en to verifythis email.If you don't need step-by-step instructions, then our public signingkey is also available athttps://bridges.torproject.org/sig and our fingerprint is [fpr]. Ifyou don't know how to use this information, then please go to the abovementioned website or contact help@rt.torproject.org for assistance.-----BEGIN PGP SIGNATURE-----Version: GnuPG v2.0.19 (GNU/Linux)[sig]-----END PGP SIGNATURE-----
Looks like I missed the second part of this ticket, that's what I get for not reading the description for a couple months. We should also copy the destination email address into the signed portion of the response, I think that's a good idea.
I wrote several tests for the functionality of this, and I'll spare the details, but python-gpgme is a horrible, horrible monster and we should not be using it.
Essentially, the TravisCI builds are failing right now (with TESTING gpg keys in place, and EMAIL_GPG_SIGN_KEY and enabled) simply because gpgme, when you do:
doesn't import that key. Instead, it imports every key in the EUID's home directory. For the continuous integration tests, this means that (because the tor package from the Debian repositories is installed as part of the CI build script) the deb.torproject.org archive signing key ends up as the first key, gpgme tries to sign a test email with it, and craps its pants.
It is about 50 lines of code to iterate though the fingerprint of every uid of every key and find the one that matches the signing subkey...I don't trust this thing. I think it is buggy and poorly designed and way too many things are going to go wrong with it. Perhaps this is just me complaining because I spent a good three months last year writing a python gnupg module, but I would actually be worried to deploy using python-gpgme. I've not yet assessed how much work it would be to replace it.
Trac: Keywords: important deleted, bridgegb-email added Priority: critical to major Status: needs_information to assigned Owner: N/Ato isis
This is fixed, and there are unittests for problems encountered, in my fix/5463-7547-7550-8241-11475-11753-email-rewritebranch (which rewrites the entirety of the old lib/bridgedb/EmailServer.py module).
There are additional fixes for the issue where libgpgme was attempting to load private keys from the process owner's $HOME directory in my fix/5463-gpgme-homedirbranch, which is currently based on the fix/5463-7547-7550-8241-11475-11753-email-rewrite branch and should be merged after it. Additionally, since all the strings were changed to be (mostly) the same as the ones which are currently in use on the HTTPS distributor, there is a translations/2014-05-07-updatebranch which should be merged which updates the gettext bridgedb.pot file.
There still is not a mechanism to include the client's email address in the signed portion of the message. I'm not exactly sure what adversarial behaviours that was intended to protect against.
There still is not a mechanism to include the client's email address in the signed portion of the message. I'm not exactly sure what adversarial behaviours that was intended to protect against.
Signing the intended recipient's e-mail address prevents the attacker from querying BridgeDB until it receives a signed message containing a malicious bridge, and then re-sending that message to one or more targeted users. (If you don't sign the destination e-mail address, there's not much point in signing BridgeDB's e-mails at all.)
Currently, the way the responses look like in the new email distributor are as follows:
The client sends an email to the distributor.
1a. If it was a valid request, the client gets the response they wanted. For example, if the client sent:
18:16:04 DEBUG L670:server.validateFrom() ORIGIN: "twisted.mail.smtp.Address('isis@127.0.0.1')"18:16:04 DEBUG L679:server.validateFrom() Got canonical domain: '127.0.0.1'18:16:04 DEBUG L487:server.lineReceived() > Received: from localhost (localhost [127.0.0.1]) for <bridges+fa@127.0.0.1>; Mon, 05 May 2014 18:16:04 +000018:16:04 DEBUG L487:server.lineReceived() > From: isis@127.0.0.118:16:04 DEBUG L487:server.lineReceived() > To: bridges+fa@127.0.0.118:16:04 DEBUG L487:server.lineReceived() > Subject: testing18:16:04 DEBUG L487:server.lineReceived() >18:16:04 DEBUG L487:server.lineReceived() > get transport obfs3
Then they would get something quite similar to this in response:
18:16:04 INFO L591:server.reply() Got an email; deciding whether to reply.18:16:04 INFO L626:server.reply() Client requested email translation: fa18:16:04 DEBUG L42:request.determineBridg() Email request was valid.18:16:04 DEBUG L106:request.withPluggableT() Parsing 'transport' line: 'get transport obfs3'18:16:04 INFO L110:request.withPluggableT() Email requested transport type: 'obfs3'18:16:04 DEBUG L53:request.determineBridg() Generating hashring filters for request.18:16:04 INFO L420:Dist.getBridgesForEmai() Attempting to return for 3 bridges for isis@127.0.0.1...18:16:05 INFO L1378:Bridges.addRing() Bridges inserted into Email-Transpo subring: 28518:16:05 DEBUG L75:Dist.getNumBridgesPerA() Returning 3 bridges from ring of len: 28518:16:05 DEBUG L1034:Bridges.getBridges() Got duplicate bridge 'f966e90fd0135a00300da797577322645b7de9fd' in main hashring for position 'f8f6fd62d22b6d29e684b0149eff7ef7a7aaf177'.18:16:05 DEBUG L181:server.generateRespons() Email contents:From: bridges@torproject.orgTo: isis@127.0.0.1Message-ID: <20140505181605.30859.509475106.1@wintermute.patternsinthevoid.net>Content-Type: text/plain; charset="utf-8"Date: Mon, 05 May 2014 18:16:05 +0000Subject: Re: testing-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512[This is an automated message; please do not reply.]Here are your bridges: obfs3 60.224.31.170:32425 fda5c4cbf4c50e099e66522b6ddd2f7088611411 obfs3 118.174.139.237:36576 46ea8d81cb30d6f0faa1064f796694e30bc4b306 obfs3 24.50.111.88:64810 ccbd222d4840a3b2c865fc558139e4c6864c17b5To enter bridges into Tor Browser, follow the instructions on the TorBrowser download page [0] to start Tor Browser.When the 'Tor Network Settings' dialogue pops up, click 'Configure' and followthe 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 andpaste the bridge lines into the text input box. Finally, click 'Connect', andyou 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-betaCOMMANDs: (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 tranport TYPEs: obfs2 obfs3 scramblesuit-----BEGIN PGP SIGNATURE-----iQMhBAEBCgELBQJTZ9VlBYMB4TOAVhSAAAAAACUAKGlzaXMrc2lnbnN1YmtleUBwYXR0ZXJuc2ludGhldm9pZC5uZXQ5RkUzOUQxQTc0Mzg5MjIzM0IzRjY2RjIyMUI1NTRFOTU5MzhGNEQwSxSAAAAAABoAKGlzaXNAcGF0dGVybnNpbnRoZXZvaWQubmV0REY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMi4aaHR0cHM6Ly9ibG9nLnBhdHRlcm5zaW50aGV2b2lkLm5ldC9wb2xpY3kudHh0LJhodHRwczovL2Jsb2cucGF0dGVybnNpbnRoZXZvaWQubmV0L2lzaXMudHh0AAoJECG1VOlZOPTQxZYQAJVzYB0V10nUHmHqxAzkXyU5IsUGJe+mnVdB+m5FS2ALqIE/+cQo75SFQeaawWrP0Qr6vrPMbNSmIm0W2aVKvtrCVGoUAdg20lr61TCj/WknGVYjkzp1SePM21ZSXh6W4YkzWTKvKjLZHpc7aNYUuuqJNSKd2nOeQ4X/2QT4MXLMEagn/oFcQPxzcW7dilGxqCCS0uxSTFpHlhLjSezNfzYFapqRq4W9poZET3azAvNk/diYfW1RF6YDqgT0NZlgbHxzaqWM8JTQeNR1RoStTd1pWZOIKIiAr7S2Hc/FV6k3lVtggEEz/89gGMH3wCm9RadUxtTWpgipCvXI8HtRjv+zFmAqk4n+YKISAXIHFB6ptL6wjrBP8i/5R8Uy37//1j80iHyAz49Qu/o9hu1Dy2Iai+hS+LraJF4KMVINes4cFr6OnplYvlM5ZjvKHI9Qis++/mmKtruss+M02pSNAQzmSo6YGbq3WpilCTjUwrAbumdWXTAg0NNq0fbAaOCvq9mF1TnqHc05GpXIi6/ggdpn4kzzc1OG60SAc/AIvh88HjOVXoHrW1d6cT75THgkTobwBSmgdDbYqIHe3t4FjNBOZX2F3vXDWjAtEuXq3h3/vTYbUDmg0TAlWHpC7yYmSzj2uHI45X2Tlx/JGr+D+ES+0TFpqgCuVRNOAk4xNjJX=sIGg-----END PGP SIGNATURE-----18:16:05 INFO L635:server.reply() Sending reply to isis@127.0.0.1
1b. The request was invalid, or the client said `"get help"`:
18:04:11 DEBUG L670:server.validateFrom() ORIGIN: "twisted.mail.smtp.Address('isis@127.0.0.1')"18:04:11 DEBUG L679:server.validateFrom() Got canonical domain: '127.0.0.1'18:04:11 DEBUG L487:server.lineReceived() > Received: from localhost (localhost [127.0.0.1]) for <bridges+fa@127.0.0.1>; Mon, 05 May 2014 18:04:11 +000018:04:11 DEBUG L487:server.lineReceived() > From: isis@127.0.0.118:04:11 DEBUG L487:server.lineReceived() > To: bridges+fa@127.0.0.118:04:11 DEBUG L487:server.lineReceived() > Subject: testing18:04:11 DEBUG L487:server.lineReceived() >18:04:11 DEBUG L487:server.lineReceived() > get help
Then the response would look like this:
18:04:11 INFO L591:server.reply() Got an email; deciding whether to reply.18:04:11 INFO L626:server.reply() Client requested email translation: fa18:04:11 INFO L122:server.createResponseB() Client requested help.18:04:12 DEBUG L181:server.generateRespons() Email contents:From: bridges@torproject.orgTo: isis@127.0.0.1Message-ID: <20140505180411.28572.546159386.0@wintermute.patternsinthevoid.net>Content-Type: text/plain; charset="utf-8"Date: Mon, 05 May 2014 18:04:11 +0000Subject: Re: testing-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512Welcome to BridgeDB!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 tranport TYPEs: obfs2 obfs3 scramblesuitBridgeDB can provide bridges with several types of Pluggable Transports[0],which can help obfuscate your connections to the Tor Network, making it moredifficult for anyone watching your internet traffic to determine that you areusing Tor.Some bridges with IPv6 addresses are also available, though some PluggableTransports aren't IPv6 compatible.Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges - without anyPluggable Transports - which maybe doesn't sound as cool, but they can stillhelp to circumvent internet censorship in many cases.[0]: https://www.torproject.org/docs/pluggable-transports.html-----BEGIN PGP SIGNATURE-----iQMhBAEBCgELBQJTZ9KbBYMB4TOAVhSAAAAAACUAKGlzaXMrc2lnbnN1YmtleUBwYXR0ZXJuc2ludGhldm9pZC5uZXQ5RkUzOUQxQTc0Mzg5MjIzM0IzRjY2RjIyMUI1NTRFOTU5MzhGNEQwSxSAAAAAABoAKGlzaXNAcGF0dGVybnNpbnRoZXZvaWQubmV0REY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMi4aaHR0cHM6Ly9ibG9nLnBhdHRlcm5zaW50aGV2b2lkLm5ldC9wb2xpY3kudHh0LJhodHRwczovL2Jsb2cucGF0dGVybnNpbnRoZXZvaWQubmV0L2lzaXMudHh0AAoJECG1VOlZOPTQPB8QAJD82VUKet9GtmEqk/i1EioR3ZJYSXKqVPMoo7a/NdI4UenSbIYN0Rsy7SBxHJmOzZ1RJ4lf2mKr/2YEGdPiIuzo/ngAYKnVXmPd4FUjTRQrIJTcnu3sOVgSbklO7c5NqoCbs6sDfHE46f/BcIhYdVFp/iPBKG8PjuE2lzqRbIqi6fn0q0+OZpxqnIg/ZC1GCPgoKuA8b1HHfu9ndvMMDiSWrFk0HWDS5fMJuOBu1ro/pjFBvvtBHBHo+0gv/86a1CWSOhMdxyNSn3Crof/XEebHD7aBgCc/eFm6EFrJMRpGg4pbsG+4cn+DoOpvJ+jMm4/EJUurOMwR9DYgjy/9uxfI4OAiJq/Ed5cGv+p3AmsNEZRQsNCHlRDTqbexXlEd8v/4mS14XqcB3aBilgkNpcKDraxtkzR7vg5te8Eno75ktQgTyUWIIa8uXkuR4lM2XExgwQ0y+4Yidj7V731DIe9ik4uLwE4V95Tf+P3u65bBYxDCQO0hQyOtKcdP6BIgjjc54VC9vm33RrVrRfXiEj+UsfFpfnR+jU6dB4xIBqebgNDF/4FcYL+egCIGGnTqUFA9SbWSrhPIxU7t9f7ghjc8BuETymWcQxWsjDwgZDa/5nSvAb4AeQLBCMPebKAJGpaHzepRKLwhI6WSY2R1m1QAQqhtPiyW2Us1pNAnAgtx=ZZ9B-----END PGP SIGNATURE-----18:04:12 INFO L635:server.reply() Sending reply to isis@127.0.0.1
They requested a copy of our public GnuPG keys:
18:15:09 DEBUG L487:server.lineReceived() > Received: from localhost (localhost [127.0.0.1]) for <bridges+fa@127.0.0.1>; Mon, 05 May 2014 18:15:09 +000018:15:09 DEBUG L487:server.lineReceived() > From: isis@127.0.0.118:15:09 DEBUG L487:server.lineReceived() > To: bridges+fa@127.0.0.118:15:09 DEBUG L487:server.lineReceived() > Subject: testing18:15:09 DEBUG L487:server.lineReceived() >18:15:09 DEBUG L487:server.lineReceived() > get key
Results in this response:
18:15:09 DEBUG L42:request.determineBridg() Email request was valid.18:15:09 INFO L125:server.createResponseB() Email requested a copy of our GnuPG key.18:15:09 DEBUG L181:server.generateRespons() Email contents:From: bridges@torproject.orgTo: isis@127.0.0.1Message-ID: <20140505181509.30859.369688437.0@wintermute.patternsinthevoid.net>Content-Type: text/plain; charset="utf-8"Date: Mon, 05 May 2014 18:15:09 +0000Subject: Re: testing-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512# This keypair contains BridgeDB's online signing and encryption subkeys. This# keypair rotates because it is kept online. However, the current online# keypair will *ALWAYS* be certified by the offline keypair (at the bottom of# this file).## If you receive an email from BridgeDB, it should be signed with the# 21B554E95938F4D0 subkey from the following keypair:# pub 4096R/8DC43A2848821E32 2013-09-11 [expires: 2014-09-11]# Key fingerprint = DF81 1109 E17C 8BF1 34B5 EEB6 8DC4 3A28 4882 1E32# uid BridgeDB <bridges@bridges.torproject.org># sub 4096R/21B554E95938F4D0 2013-09-11 [expires: 2014-09-11]# Key fingerprint = 9FE3 9D1A 7438 9223 3B3F 66F2 21B5 54E9 5938 F4D0# sub 4096R/E7793047C5B54232 2013-09-11 [expires: 2014-09-11]# Key fingerprint = CFFB 8469 9048 37E7 8CAE 322C E779 3047 C5B5 4232-----BEGIN PGP PUBLIC KEY BLOCK-----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ieIZ-----END PGP PUBLIC KEY BLOCK-----# The following keypair is BridgeDB's offline certification-only keypair. It# is used to sign new online signing/encryption keypairs.## If you import this key and mark it as trusted, emails from BridgeDB (if# signed correctly with the online keypair above) should always be trusted. To# do this, open a shell and do:## $ curl -O https://bridges.torproject.org/keys# $ gpg --import keys# $ gpg --check-sigs 7B78437015E63DF47BB1270ACBD97AA24E8E472E# $ gpg --edit-key 7B78437015E63DF47BB1270ACBD97AA24E8E472E## Then type 'trust' to set the trust level. Choose a number that you like.# Next type 'quit'. Finally, to create a local signature which will will not# be uploaded to keyservers:## $ gpg --lsign-key 7B78437015E63DF47BB1270ACBD97AA24E8E472E## pub 16384R/CBD97AA24E8E472E 2013-10-12# Key fingerprint = 7B78 4370 15E6 3DF4 7BB1 270A CBD9 7AA2 4E8E 472E# uid BridgeDB (Offline ID Key) <bridges@bridges.torproject.org>-----BEGIN PGP PUBLIC KEY BLOCK-----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JdC7-----END PGP PUBLIC KEY BLOCK----------BEGIN PGP SIGNATURE-----iQMhBAEBCgELBQJTZ9UtBYMB4TOAVhSAAAAAACUAKGlzaXMrc2lnbnN1YmtleUBwYXR0ZXJuc2ludGhldm9pZC5uZXQ5RkUzOUQxQTc0Mzg5MjIzM0IzRjY2RjIyMUI1NTRFOTU5MzhGNEQwSxSAAAAAABoAKGlzaXNAcGF0dGVybnNpbnRoZXZvaWQubmV0REY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMi4aaHR0cHM6Ly9ibG9nLnBhdHRlcm5zaW50aGV2b2lkLm5ldC9wb2xpY3kudHh0LJhodHRwczovL2Jsb2cucGF0dGVybnNpbnRoZXZvaWQubmV0L2lzaXMudHh0AAoJECG1VOlZOPTQdXMP/A78b7eekpJD0zH3TwGPMQCX0iM67fL2N1VH4WcrqkUmYQM2N+NNO5qc94iGYZyros2Oi+TDc0es0Xve3Tck3o6IdxpksKlZ9tbbdeP9ruBD/q50V0eKfvOAEu+BLSIxEzBYMGoCHWNP788rTu1Y+R5TsgsIdkfla4rbpq5ocsCXxp2Tsj9gdi/uUH1oh5ZEk9GwBVbuWzaJtKHl6f07HMzrKQwBHfsix7dPW+FRVgNKl5Vl3x2MijLr77boOF7PzAawYqYE0C7ze8N+Q6ReTTjNEyBsHkc30Jek2ZcZstNbHDDUXFUI0fcXbqN4atRE3v68JUhWvEps7NAuH6SrmD7KLg/Nd6vrFp3uVmJxIlkb5r98iOlabIGi1db+ZN8FR52ueVOqcU+Qz4C/oQ2xWKfkaoqCLfdNe+89u5izqzbGDiMQBp6nGAS+S8bKG3Zs0lIcX00ZeIFOWU7tW79FvJPmOHD2gE2ZF4bXGfZuFEbyjXzsPnjRiODl4ju7SyINnWLUnjKCHYxz5Ie56td75Xzup9Q554bHRKxwOmFiMEteXKhQZdqVcEARS02kb9wXYuJhbrMewwc/15LeyvfGMk2sbcjawbteVtGemy+ruPFOTMCMprCfimIS+nJLp6LLmSu4L+uvzrYdfLgSHeCTGLUSkTQvodpnN+YomPSSbTaU=bJPk-----END PGP SIGNATURE-----18:15:09 INFO L635:server.reply() Sending reply to isis@127.0.0.1
The client sends too many valid requests (after they have already received help). In this case, they'll get the normal rate-limiting informational reply (except it's signed):
18:17:11 DEBUG L42:request.determineBridg() Email request was valid.18:17:11 DEBUG L106:request.withPluggableT() Parsing 'transport' line: 'get transport obfs3'18:17:11 INFO L110:request.withPluggableT() Email requested transport type: 'obfs3'18:17:11 DEBUG L53:request.determineBridg() Generating hashring filters for request.18:17:11 INFO L420:Dist.getBridgesForEmai() Attempting to return for 3 bridges for isis@127.0.0.1...18:17:11 INFO L426:Dist.getBridgesForEmai() Client isis@127.0.0.1 must wait another 10728 seconds.18:17:11 INFO L430:Dist.getBridgesForEmai() Sending duplicate request warning.18:17:11 INFO L128:server.createResponseB() Got a mail too frequently: Must wait 10728 seconds.18:17:11 DEBUG L181:server.generateRespons() Email contents:From: bridges@torproject.orgTo: isis@127.0.0.1Message-ID: <20140505181711.30859.1077507167.2@wintermute.patternsinthevoid.net>Content-Type: text/plain; charset="utf-8"Date: Mon, 05 May 2014 18:17:11 +0000Subject: Re: testing-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512[This is an automated message; please do not reply.]You have exceeded the rate limit. Please slow down! The minimum time betweenemails is 3 hours. All further emails during this time period will be ignored.-----BEGIN PGP SIGNATURE-----iQMhBAEBCgELBQJTZ9WnBYMB4TOAVhSAAAAAACUAKGlzaXMrc2lnbnN1YmtleUBwYXR0ZXJuc2ludGhldm9pZC5uZXQ5RkUzOUQxQTc0Mzg5MjIzM0IzRjY2RjIyMUI1NTRFOTU5MzhGNEQwSxSAAAAAABoAKGlzaXNAcGF0dGVybnNpbnRoZXZvaWQubmV0REY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMi4aaHR0cHM6Ly9ibG9nLnBhdHRlcm5zaW50aGV2b2lkLm5ldC9wb2xpY3kudHh0LJhodHRwczovL2Jsb2cucGF0dGVybnNpbnRoZXZvaWQubmV0L2lzaXMudHh0AAoJECG1VOlZOPTQWMoP/1b4C1klisjrm5B7J2Uz+ClxW2jWO03Ec6VyZd7GGyb1texDefGaiiG4GEUJlEq7IccZ++OZxkkQk7cx9/m53Q+FHM/jAOIIeOpP+q8sWb0iH8X+UVxkzxKWFbqD+sUDI9YL/o3dEq48Cfy0Qd4ox4d8ubwgw1K8eL1wGHeUkiqCySvVTPRgVd2cyefBDJCP9B+zvJupayqqnllAl2WnqawNNuS+06xuVhMn3dY2o6hZe08e7YZfLUQbr0fCeV3CnDh4Axo48RU5M9dQHKn7D523+NO0ByjCNtmLHBppU0EsNUvkhM4N2XtDyZSeyrdamvPzfxaIKAsOfYrUvE8ADbAw3niVQoPTLza7WJoTwCKD0cyJJ9e0UDcgg6/kj1lUUlFYAetPDNQv7l9OFCzKreWA43LQfH8csCUagN6Z7uaX6CyqCU0yLIQOlpHm4Odk+kLwvJ2U6goJ3MaB9tnTav4MdLT/KL23UyxJeeF3WPBWRlnN9a6Irfp4PryrY5PUoEj0iqtHFx6VCmAoot3A2kpo517PbFTP3wsnL2N7XV4o0sEMCKPW4xjoIV5dCvVYSJSmjjG4ebu882tenbKW5aidbBWb+SVAcchnvUdr/FTILRI7+kiB/Z+lfujvxTwb/EjPI//r/QwGk9Lf7YILZWzNJ2HuD0QIvkamrNuCjpOB=CqjB-----END PGP SIGNATURE-----18:17:11 INFO L635:server.reply() Sending reply to isis@127.0.0.1
And finally, the server logs show the following if a client has already received the rate-limit warning and is no longer being replied to:
8:17:48 DEBUG L670:server.validateFrom() ORIGIN: "twisted.mail.smtp.Address('isis@127.0.0.1')"18:17:48 DEBUG L679:server.validateFrom() Got canonical domain: '127.0.0.1'18:17:48 DEBUG L487:server.lineReceived() > Received: from localhost (localhost [127.0.0.1]) for <bridges+fa@127.0.0.1>; Mon, 05 May 2014 18:17:48 +000018:17:48 DEBUG L487:server.lineReceived() > From: isis@127.0.0.118:17:48 DEBUG L487:server.lineReceived() > To: bridges+fa@127.0.0.118:17:48 DEBUG L487:server.lineReceived() > Subject: testing18:17:48 DEBUG L487:server.lineReceived() >18:17:48 DEBUG L487:server.lineReceived() > get transport obfs318:17:48 INFO L591:server.reply() Got an email; deciding whether to reply.18:17:48 INFO L626:server.reply() Client requested email translation: fa18:17:48 DEBUG L42:request.determineBridg() Email request was valid.18:17:48 DEBUG L106:request.withPluggableT() Parsing 'transport' line: 'get transport obfs3'18:17:48 INFO L110:request.withPluggableT() Email requested transport type: 'obfs3'18:17:48 DEBUG L53:request.determineBridg() Generating hashring filters for request.18:17:48 INFO L420:Dist.getBridgesForEmai() Attempting to return for 3 bridges for isis@127.0.0.1...18:17:48 INFO L426:Dist.getBridgesForEmai() Client isis@127.0.0.1 must wait another 10691 seconds.18:17:48 INFO L131:server.createResponseB() Client was warned.
There still is not a mechanism to include the client's email address in the signed portion of the message. I'm not exactly sure what adversarial behaviours that was intended to protect against.
Signing the intended recipient's e-mail address prevents the attacker from querying BridgeDB until it receives a signed message containing a malicious bridge, and then re-sending that message to one or more targeted users. (If you don't sign the destination e-mail address, there's not much point in signing BridgeDB's e-mails at all.)
Good point. I agree completely, and I'll hack it in right now. :)
There still is not a mechanism to include the client's email address in the signed portion of the message. I'm not exactly sure what adversarial behaviours that was intended to protect against.
Signing the intended recipient's e-mail address prevents the attacker from querying BridgeDB until it receives a signed message containing a malicious bridge, and then re-sending that message to one or more targeted users. (If you don't sign the destination e-mail address, there's not much point in signing BridgeDB's e-mails at all.)
Good point. I agree completely, and I'll hack it in right now. :)
I'm going to add timestamps too, so that an earlier email cannot be replayed. I.e., when the NSA is like "Yo', we got the extra wiretaps installed around the boxes with those IPs. Let's resend and get 'em."
I'm going to add timestamps too, so that an earlier email cannot be replayed. I.e., when the NSA is like "Yo', we got the extra wiretaps installed around the boxes with those IPs. Let's resend and get 'em."
OpenPGP already includes a timestamp in the signature packet, but adding a timestamp in the text is a good idea too, if users won't be confused by the time zone. (MUAs which display the timestamp are likely to display it adjusted to the user's TZ; unfortunately, the one MUA I used with OpenPGP support didn't display the timestamp.)
Done. It's in my fix/5463-sign-client-email-addrbranch. It's based on fix/5463-gpgme-homedir, which in turn is based on fix/5463-7547-7550-8241-11475-11753-email-rewrite which are the two branches mentioned above which fix all these tickets.
nice job, isis. i'm thankful that your comment my fix/5463-7547-7550-8241-11475-11753-email-rewrite branch (which rewrites the entirety of the old lib/bridgedb/EmailServer.py module) was not actually a complete rewrite, otherwise this review would take a lot longer :)
This review doesn't include anything more than a cursory skimming of the HTML template modifications or a proper review of the unit tests. Most of what follows are a bunch of nitpicky details that are not blockers. A few of them should be separate tickets, tbh, too. The only parts that I think should be reconsidered are the unconditional logging of email addresses. I really think those should be scrubbed except for when safe logging is disabled, unless there's a good reason?
This only includes fix/5463-7547-7550-8241-11475-11753-email-rewrite. fix/5463-sign-client-email-addr and fix/5463-gpgme-homedir will (hopefully) follow in a few hours.
lib/bridgedb/Dist.py:419 - need to scrub email address
lib/bridgedb/Dist.py:426 - need to scrub email address
lib/bridgedb/Dist.py:428 - need to scrub email address
lib/bridgedb/Dist.py:433 - need to scrub email address
Bridges.isBlocked() is buggy. It returns true if any of a bridges ipaddr:port pair are not known to be blocked in the country. 1) When the filter returns true, we don't know which pair, 2) we should somehow mark the bridge as unhealthy and only return it if there aren't other options
determineBridgeRequestOptions(): the presence of "get" defines an email as valid? I don't have a significantly better answer except that maybe only set it when a valid command is found? Not much is gained by this, though.
EmailBridgeRequest:withoutBlockInCountry(): Should we support multiple country codes per line? space and/or comma separated?
Should our response inform the user that we only used the last transport specified in their email request?
determineBridgeRequestOptions(): There's no harm in setting request.isValid(True) and request.wantsKey(True) prior to raises the exception, but is there a reason for doing this?
lib/bridgedb/email/server.py:183 - Do we want to unconditionally log the client's email address?
While the email server is getting an upgrade, should we also bump it to use the ESMTPFactory? We won't see any benefit from this, but I wonder if there's a reason for us to continue using SMTP.
lib/bridgedb/email/server.py:316,328,332 - trailing white space after read(), seek(), tell()
lib/bridgedb/email/server.py:732 - The schedule was originally going to be used to partition the hash-rings so that bridgedb can rotate through the bridges over a given period, (obviously) it's not doing this right now. If we had higher bridge churn then this would be more useful.
lib/bridgedb/email/templates.py:33
Is there a benefit to
while not len(command) >= 25:
rather than
while len(command) < 25:
?
template.gettext(strings.HOWTO_TBB[1]) % strings.EMAIL_SPRINTF["HOWTO_TBB1"] - adds an extra space between the words. "the %s Tor"
lib/bridgedb/strings.py:116 - s/the word the word/the word/ and s/tranlate/translate/
As for the other two, they both lgtm but I haven't tested them yet. I'm wondering if we should add another line to addBridgeAnswer() that asks the user to check the email address and timestamp in the footer and discard the email if either of them are incorrect. I doubt most users will think twice about an old timestamp or wrong email address unless we explicitly mention that these should be correct.
BridgeDB must also include the address to which it sent a message in the GPG-signed text, and warn users that they should verify that BridgeDB messages are GPG-signed and that the e-mail address in the signed message matches the e-mail address which the user requested bridges with.
After re-reading the ticket's description I realized that, in addition to my last comment, I'm not sure we sufficiently warn users about the unfortunate side effects of not verifying the signature. As far as I see, bridgedb.asc is the only place we mention verifying the sig, and a user only sees this if they explicitly request the key. We should try to find a place to mention this in the other templates. I think we should be realistic and take into account the fact that only a small fraction of end-users will check the sig, regardless of what the email says, and if we add too much information then most users won't read any of it. This may be a small challenge.
Bridges.isBlocked() is buggy. It returns true if any of a bridges ipaddr:port pair are not known to be blocked in the country. 1) When the filter returns true, we don't know which pair, 2) we should somehow mark the bridge as unhealthy and only return it if there aren't other options
Yeah, none of the blocking check code currently works. I believe there is a ticket for this...
determineBridgeRequestOptions(): the presence of "get" defines an email as valid? I don't have a significantly better answer except that maybe only set it when a valid command is found? Not much is gained by this, though.
Yeah... so I mostly added that because I assumed that other subclasses of bridgedb.bridgerequest.BridgeRequest would need a way to check that the request was valid. Because get was the only thing common to all request strings, it was what I chose to determine if the person/robot was able to follow basic instruction... not really necessary, and if it turns out to be a problem then we can just automatically set isValid(True).
EmailBridgeRequest:withoutBlockInCountry(): Should we support multiple country codes per line? space and/or comma separated?
But why would you be traveling between multiple countries which block Tor bridges so fast that you need bridges which support both countries?
Should our response inform the user that we only used the last transport specified in their email request?
Perhaps. But if they were doing things like what's in the test_createResponseBody_bridges_obfsobfswebzipv6() unittest, then they are probably trying to mess with us somehow. That, or get multiple bridge types simultaneously. If someone wants to wreck theirs and the bridges' anonymity by probing the internet with every PT type on the wiki everytime they fire up tor or TBB, then they can slowly accumulate the collection of different PTs they need to do it over the course of a day or so.
I guess what I mean is: "I'd rather not help/inform/enable users who appear to be somewhat-abusing BridgeDB in to destroy their anonymity and burn bridges as fast as possible."
Also, in general, I'm for less wall-of-text emails, as someone who currently can't handle reading/answering the amount of email they receive.
determineBridgeRequestOptions(): There's no harm in setting request.isValid(True) and request.wantsKey(True) prior to raises the exception, but is there a reason for doing this?
Another somewhat awkward API design choice in this case. I assumed that normally, a distributor would want to set wantsKey(True), and then include the keys with whatever response it gives later. However, since we don't currently support PGP/MIME and/or MIME/multipart, we can't attach the key, and it has to occupy the entire body of the email (ugh, gross).
Later, if someone hacks in MIME support, the EmailRequestedKey exception should be rather unnecessary, and we could just tack the key on as an attachment to whatever else we're sending.
I'm not sure if any other distributors in the future will want a wantsKey() method.
lib/bridgedb/email/server.py:183 - Do we want to unconditionally log the client's email address?
MailMessage:getRecipient() - incoming - DOCDOC, and s/param/var/
Fixed, thanks again.
While the email server is getting an upgrade, should we also bump it to use the ESMTPFactory? We won't see any benefit from this, but I wonder if there's a reason for us to continue using SMTP.
Hmm. Not sure? I thought that no mail servers actually support full ESMTP, and there's risk with not being able to talk to them, but we should only be talking to the local Postfix, IIRC.
Though, did you have a specific extension in mind that would help with something?
lib/bridgedb/email/server.py:316,328,332 - trailing white space after read(), seek(), tell()
lib/bridgedb/email/server.py:732 - The schedule was originally going to be used to partition the hash-rings so that bridgedb can rotate through the bridges over a given period, (obviously) it's not doing this right now. If we had higher bridge churn then this would be more useful.
Yeah... I still keep wondering if we should re-enable that.
I ended up using a schedule for implementing the gimp-captcha timeouts in #11215 (moved) though, so they're still useful.
lib/bridgedb/strings.py:116 - s/the word the word/the word/ and s/tranlate/translate/
Robert Ransom gave me a patch for this one, and it's already merged. Thanks, both of you!
I'll respond to the rest of this tomorrow:
lib/bridgedb/email/templates.py:33
Is there a benefit to
{{{
while not len(command) >= 25:
}}}
rather than
{{{
while len(command) < 25:
}}}
?
template.gettext(strings.HOWTO_TBB[1]) % strings.EMAIL_SPRINTF["HOWTO_TBB1"] - adds an extra space between the words. "the %s Tor"
Trac: Status: needs_review to closed Resolution: N/Ato fixed
After switching to python-gnupg in #10385 (moved), this is working again. I just received the following email from BridgeDB after deploying 0.3.0:
From: bridges+de@torproject.orgTo: isis@riseup.netCc:Bcc:Subject: Re: (no subject)Reply-To:In-Reply-To: <30168958158219d97dfcba15c42b1634@riseup.net>Delivered-To: <isis@patternsinthevoid.net>-----BEGIN PGP SIGNED MESSAGE-----Hash: SHA512Hey, isis! Welcome to BridgeDB!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 obfs4 scramblesuit fteBridgeDB can provide bridges with several types of Pluggable Transports[0],which can help obfuscate your connections to the Tor Network, making it moredifficult for anyone watching your internet traffic to determine that you areusing Tor.Some bridges with IPv6 addresses are also available, though some PluggableTransports aren't IPv6 compatible.Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges - without anyPluggable Transports - which maybe doesn't sound as cool, but they can stillhelp to circumvent internet censorship in many cases.[0]: https://www.torproject.org/docs/pluggable-transports.html -- <3 BridgeDB______________________________________________________________________Public Keys: https://bridges.torproject.org/keysThis email was generated with rainbows, unicorns, and sparklesfor isis@riseup.net on Saturday, 21 March, 2015 at 03:28:48.-----BEGIN PGP SIGNATURE-----iQIcBAEBCgAGBQJVDOVwAAoJECG1VOlZOPTQFX8QAI3IF1Ce/77Q0WeI7M1v2d2eZJzLuxRRjQO0TiWUrRouOA3+gXTlhVs+bqCDxf52POd7OOWj6ojBptesf0gy+6X6vw647fD/cJFKxqEkU34aV1s3SK991G30oGMMKguIDlw3jdtyNSemqw9rrYP33JHP/G/5SLGLYnuZgek0WntOGcikCqikECxRpD7//MZPH0MoqkgPSh8MUKTAWLYJ0g3+xFq7WMIfVMnyaR2UOq1uEYpfJ+Pli/TeYphvPtmeTcrLmFXDtm/0rtjxgCDyX67Y0QEXAeyMJWDE2gTD0P3Ur+IVTZanIZsXyyGrmiggOIPo0JakDUnDUjAaKaBwDlAnbMJ/t+5Bnl8NAUahDOltThCLE9432P4vyRrvnZPYE+55Bc5AX078dUNxoaWD74DHxCKf84VFVIHzK9wyCPFdmxtsi0UUi7rc8kr0n1Rnwe4XDfb3EDSsNZyGLNNDOjsMOuxjnl0KhuVThPR/xlnb3Zic7BsRHoZhU4eBn/k6Ex+BkrNAC4QCWqY8AOgHXQXk5HMjQzQsJs/GrM60OK05+3yjVIFaM/a7d1RTAutt07uR9JeV3fj2TgA1s7/xjTOjHkxGtVpOq+WfwuWC3hXrrGcdxRXEkj4VDzd6p2Wu16+jcsX6zuhLgLcgYBb77fgCPwRwpUowl8FDAZL7U159=BEzx-----END PGP SIGNATURE-----
Trac: Resolution: N/Ato fixed Status: reopened to closed