tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2020
- 18 participants
- 1587 discussions

27 May '20
commit 1958bbb7e95df0f810e219955595f353933e1302
Author: Philipp Winter <phw(a)nymity.ch>
Date: Tue Mar 31 09:37:37 2020 -0700
Make our email autoresponder more usable.
So far, our autoresponder would only send you bridges if your request
was valid. Unfortunately, it's not very easy to figure out what a
correct request looks like. This patch returns bridges regardless of if
the request was valid or not. We also remove the "help" autoresponse
because there's no longer a need for it, and we simplify BridgeDB's auto
response, hopefully making it less frustrating for users.
This fixes <https://bugs.torproject.org/30941>.
---
CHANGELOG | 6 ++
bridgedb/distributors/email/autoresponder.py | 10 --
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 20 ++--
bridgedb/distributors/email/templates.py | 83 +++++-----------
bridgedb/i18n/templates/bridgedb.pot | 143 +++++++++++----------------
bridgedb/metrics.py | 7 +-
bridgedb/strings.py | 49 ++++-----
bridgedb/test/test_email_autoresponder.py | 5 +-
bridgedb/test/test_email_request.py | 46 ++++-----
bridgedb/test/test_email_templates.py | 31 +-----
11 files changed, 151 insertions(+), 255 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 3e179e1..f85283b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ * FIXES https://bugs.torproject.org/30941
+ Make our email responder more usable. This patch removes the concept of
+ "valid" email commands and returns bridges (obfs4, for now) no matter
+ what the user sends. BridgeDB still supports email commands in case the
+ user needs a vanilla or IPv6 bridge.
+
* FIXES https://bugs.torproject.org/29686
Rename files that contain "Bridges" to "bridgerings", to eliminate
headache on file systems that are case insensitive.
diff --git a/bridgedb/distributors/email/autoresponder.py b/bridgedb/distributors/email/autoresponder.py
index 3711eae..5e1fcd0 100644
--- a/bridgedb/distributors/email/autoresponder.py
+++ b/bridgedb/distributors/email/autoresponder.py
@@ -55,7 +55,6 @@ from bridgedb import safelog
from bridgedb.distributors.email import dkim
from bridgedb.distributors.email import request
from bridgedb.distributors.email import templates
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from bridgedb.distributors.email.distributor import EmailRequestedKey
from bridgedb.distributors.email.distributor import TooSoonEmail
from bridgedb.distributors.email.distributor import IgnoreEmail
@@ -98,18 +97,9 @@ def createResponseBody(lines, context, client, lang='en'):
bridgeRequest = request.determineBridgeRequestOptions(lines)
bridgeRequest.client = str(client)
- # The request was invalid, respond with a help email which explains
- # valid email commands:
- if not bridgeRequest.isValid():
- raise EmailRequestedHelp("Email request from '%s' was invalid."
- % str(client))
-
# Otherwise they must have requested bridges:
interval = context.schedule.intervalStart(time.time())
bridges = context.distributor.getBridges(bridgeRequest, interval)
- except EmailRequestedHelp as error:
- logging.info(error)
- return templates.buildWelcomeText(translator, client)
except EmailRequestedKey as error:
logging.info(error)
return templates.buildKeyMessage(translator, client)
diff --git a/bridgedb/distributors/email/distributor.py b/bridgedb/distributors/email/distributor.py
index a90e725..c6ac2fd 100644
--- a/bridgedb/distributors/email/distributor.py
+++ b/bridgedb/distributors/email/distributor.py
@@ -20,7 +20,7 @@ bridgedb.distributors.email.autoresponder
A :class:`~bridgedb.distribute.Distributor` which hands out :class:`bridges
<bridgedb.bridges.Bridge>` to clients via an email interface.
-.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailRequestedHelp EmailRequestedKey EmailDistributor
+.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailRequestedKey EmailDistributor
:parts: 1
"""
@@ -55,10 +55,6 @@ class TooSoonEmail(addr.BadEmail):
"""Raised when we got a request from this address too recently."""
-class EmailRequestedHelp(Exception):
- """Raised when a client has emailed requesting help."""
-
-
class EmailRequestedKey(Exception):
"""Raised when an incoming email requested a copy of our GnuPG keys."""
diff --git a/bridgedb/distributors/email/request.py b/bridgedb/distributors/email/request.py
index 83c203d..90576c1 100644
--- a/bridgedb/distributors/email/request.py
+++ b/bridgedb/distributors/email/request.py
@@ -43,8 +43,8 @@ from __future__ import unicode_literals
import logging
import re
+from bridgedb import strings
from bridgedb import bridgerequest
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from bridgedb.distributors.email.distributor import EmailRequestedKey
@@ -61,7 +61,6 @@ UNBLOCKED_PATTERN = re.compile(UNBLOCKED_REGEXP)
#: Regular expressions that we use to match for email commands. Any command is
#: valid as long as it wasn't quoted, i.e., the line didn't start with a '>'
#: character.
-HELP_LINE = re.compile("([^>].*)?h[ae]lp")
GET_LINE = re.compile("([^>].*)?get")
KEY_LINE = re.compile("([^>].*)?key")
IPV6_LINE = re.compile("([^>].*)?ipv6")
@@ -69,14 +68,13 @@ TRANSPORT_LINE = re.compile("([^>].*)?transport")
UNBLOCKED_LINE = re.compile("([^>].*)?unblocked")
def determineBridgeRequestOptions(lines):
- """Figure out which :mod:`~bridgedb.filters` to apply, or offer help.
+ """Figure out which :mod:`~bridgedb.filters` to apply.
.. note:: If any ``'transport TYPE'`` was requested, or bridges not
blocked in a specific CC (``'unblocked CC'``), then the ``TYPE``
and/or ``CC`` will *always* be stored as a *lowercase* string.
:param list lines: A list of lines from an email, including the headers.
- :raises EmailRequestedHelp: if the client requested help.
:raises EmailRequestedKey: if the client requested our GnuPG key.
:rtype: :class:`EmailBridgeRequest`
:returns: A :class:`~bridgerequest.BridgeRequest` with all of the requested
@@ -92,9 +90,6 @@ def determineBridgeRequestOptions(lines):
if not line: skippedHeaders = True
if not skippedHeaders: continue
- if HELP_LINE.match(line) is not None:
- raise EmailRequestedHelp("Client requested help.")
-
if GET_LINE.match(line) is not None:
request.isValid(True)
logging.debug("Email request was valid.")
@@ -108,6 +103,17 @@ def determineBridgeRequestOptions(lines):
if UNBLOCKED_LINE.match(line) is not None:
request.withoutBlockInCountry(line)
+ # We cannot expect all users to understand BridgeDB's commands, so we will
+ # return bridges even if the request was invalid.
+ if not request.isValid():
+ logging.debug("Email request was invalid.")
+ request.isValid(True)
+ # We will respond with our default transport protocol.
+ if not len(request.transports):
+ # Note that this variable must satisfy TRANSPORT_PATTERN.
+ default_transport = "transport %s" % strings._getDefaultTransport()
+ request.withPluggableTransportType(default_transport)
+
logging.debug("Generating hashring filters for request.")
request.generateFilters()
return request
diff --git a/bridgedb/distributors/email/templates.py b/bridgedb/distributors/email/templates.py
index d618c37..2eb0a31 100644
--- a/bridgedb/distributors/email/templates.py
+++ b/bridgedb/distributors/email/templates.py
@@ -21,9 +21,6 @@ bridgedb.distributors.email.templates
Templates for formatting emails sent out by the email distributor.
"""
-from __future__ import print_function
-from __future__ import unicode_literals
-
import logging
import os
@@ -34,12 +31,17 @@ from bridgedb.distributors.email.distributor import MAX_EMAIL_RATE
def addCommands(template):
- """Add some text telling a client about supported email command, as well as
- which Pluggable Transports are currently available.
+ """Add text telling a client about supported email command.
+
+ :type template: ``gettext.NullTranslation`` or ``gettext.GNUTranslation``
+ :param template: A gettext translations instance, optionally with fallback
+ languages set.
+ :rtype: str
+ :returns: A string explaining email commands.
"""
# Tell them about the various email commands:
cmdlist = []
- cmdlist.append(template.gettext(strings.EMAIL_MISC_TEXT.get(3)))
+ cmdlist.append(template.gettext(strings.EMAIL_MISC_TEXT.get(3)) + "\n")
for cmd, desc in strings.EMAIL_COMMANDS.items():
command = ' '
command += cmd
@@ -48,29 +50,20 @@ def addCommands(template):
command += template.gettext(desc)
cmdlist.append(command)
- commands = "\n".join(cmdlist) + "\n\n"
- # And include the currently supported transports:
- commands += template.gettext(strings.EMAIL_MISC_TEXT.get(5))
- commands += "\n"
- for pt in strings._getSupportedTransports():
- commands += ' ' + pt + "\n"
+ return "\n".join(cmdlist) + "\n\n"
- return commands
+def addGreeting(template):
+ """Our "greeting" clarifies that this is an automated email response.
-def addGreeting(template, clientName=None, welcome=False):
- greeting = ""
- clientName = clientName.decode('utf-8') if isinstance(clientName, bytes) else clientName
-
- if not clientName:
- greeting = template.gettext(strings.EMAIL_MISC_TEXT[7])
- else:
- greeting = template.gettext(strings.EMAIL_MISC_TEXT[6]) % clientName
+ :type template: ``gettext.NullTranslation`` or ``gettext.GNUTranslation``
+ :param template: A gettext translations instance, optionally with fallback
+ languages set.
+ :rtype: str
+ :returns: A string containing our "greeting".
+ """
- if greeting:
- if welcome:
- greeting += u' '
- greeting += template.gettext(strings.EMAIL_MISC_TEXT[4])
- greeting += u'\n\n'
+ greeting = template.gettext(strings.EMAIL_MISC_TEXT[0])
+ greeting += u"\n\n"
return greeting
@@ -79,11 +72,10 @@ def addKeyfile(template):
def addBridgeAnswer(template, answer):
# Give the user their bridges, i.e. the `answer`:
- bridgeLines = template.gettext(strings.EMAIL_MISC_TEXT[0])
- bridgeLines += u"\n\n"
+ bridgeLines = u""
bridgeLines += template.gettext(strings.EMAIL_MISC_TEXT[1])
bridgeLines += u"\n\n"
- bridgeLines += u"%s\n\n" % answer
+ bridgeLines += u"%s\n" % answer
return bridgeLines
@@ -94,40 +86,15 @@ def addHowto(template):
:param template: A gettext translations instance, optionally with fallback
languages set.
"""
- howToTBB = template.gettext(strings.HOWTO_TBB[1]) % strings.EMAIL_SPRINTF["HOWTO_TBB1"]
- howToTBB += u'\n\n'
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB1")
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB2")
- howToTBB += strings.EMAIL_REFERENCE_LINKS.get("HOWTO_TBB3")
- howToTBB += u'\n\n'
- return howToTBB
+ return template.gettext(strings.HOWTO_TBB[2])
def buildKeyMessage(template, clientAddress=None):
message = addKeyfile(template)
return message
-def buildWelcomeText(template, clientAddress=None):
- sections = []
- sections.append(addGreeting(template, clientAddress.local, welcome=True))
-
- commands = addCommands(template)
- sections.append(commands)
-
- # Include the same messages as the homepage of the HTTPS distributor:
- welcome = template.gettext(strings.WELCOME[0]) % strings.EMAIL_SPRINTF["WELCOME0"]
- welcome += template.gettext(strings.WELCOME[1])
- welcome += template.gettext(strings.WELCOME[2]) % strings.EMAIL_SPRINTF["WELCOME2"]
- sections.append(welcome)
-
- message = u"\n\n".join(sections)
- # Add the markdown links at the end:
- message += strings.EMAIL_REFERENCE_LINKS.get("WELCOME0")
-
- return message
-
def buildAnswerMessage(template, clientAddress=None, answer=None):
try:
- message = addGreeting(template, clientAddress.local)
+ message = addGreeting(template)
message += addBridgeAnswer(template, answer)
message += addHowto(template)
message += u'\n\n'
@@ -139,11 +106,9 @@ def buildAnswerMessage(template, clientAddress=None, answer=None):
return message
def buildSpamWarning(template, clientAddress=None):
- message = addGreeting(template, clientAddress.local)
+ message = addGreeting(template)
try:
- message += template.gettext(strings.EMAIL_MISC_TEXT[0])
- message += u"\n\n"
message += template.gettext(strings.EMAIL_MISC_TEXT[2]) \
% str(MAX_EMAIL_RATE / 3600)
except Exception as error: # pragma: no cover
diff --git a/bridgedb/i18n/templates/bridgedb.pot b/bridgedb/i18n/templates/bridgedb.pot
index 8fa69c6..65f8ca6 100644
--- a/bridgedb/i18n/templates/bridgedb.pot
+++ b/bridgedb/i18n/templates/bridgedb.pot
@@ -5,11 +5,11 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: bridgedb 0.9.4+8.g5afd164.dirty\n"
+"Project-Id-Version: bridgedb 0.10.0+8.g97621c0\n"
"Report-Msgid-Bugs-To: "
"'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…"
"=bridgedb-reported,msgid&cc=isis,sysrqb&owner=isis'\n"
-"POT-Creation-Date: 2020-03-24 10:22-0700\n"
+"POT-Creation-Date: 2020-04-06 13:53-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL(a)li.org>\n"
@@ -66,6 +66,10 @@ msgstr ""
msgid "Changelog"
msgstr ""
+#: bridgedb/distributors/https/templates/base.html:102
+msgid "Public Keys"
+msgstr ""
+
#: bridgedb/distributors/https/templates/bridges.html:35
msgid "Select All"
msgstr ""
@@ -83,7 +87,7 @@ msgstr ""
#. for Italian, you might translate this into "Mama mia!",
#. or for French: "Sacrebleu!". :)
#: bridgedb/distributors/https/templates/bridges.html:67
-#: bridgedb/distributors/https/templates/bridges.html:125
+#: bridgedb/distributors/https/templates/bridges.html:119
msgid "Uh oh, spaghettios!"
msgstr ""
@@ -97,12 +101,12 @@ msgid ""
"your bridge lines onto mobile and other devices."
msgstr ""
-#: bridgedb/distributors/https/templates/bridges.html:131
+#: bridgedb/distributors/https/templates/bridges.html:125
msgid "There currently aren't any bridges available..."
msgstr ""
-#: bridgedb/distributors/https/templates/bridges.html:133
-#: bridgedb/distributors/https/templates/bridges.html:137
+#: bridgedb/distributors/https/templates/bridges.html:127
+#: bridgedb/distributors/https/templates/bridges.html:131
#, python-format
msgid " Perhaps you should try %s going back %s and choosing a different bridge type!"
msgstr ""
@@ -176,15 +180,15 @@ msgstr ""
msgid "%sG%set Bridges"
msgstr ""
-#: bridgedb/strings.py:43
-msgid "[This is an automated message; please do not reply.]"
+#: bridgedb/strings.py:42
+msgid "[This is an automated email.]"
msgstr ""
-#: bridgedb/strings.py:45
+#: bridgedb/strings.py:44
msgid "Here are your bridges:"
msgstr ""
-#: bridgedb/strings.py:47
+#: bridgedb/strings.py:46
#, python-format
msgid ""
"You have exceeded the rate limit. Please slow down! The minimum time between\n"
@@ -192,48 +196,17 @@ msgid ""
"ignored."
msgstr ""
-#: bridgedb/strings.py:50
-msgid "COMMANDs: (combine COMMANDs to specify multiple options simultaneously)"
-msgstr ""
-
-#. TRANSLATORS: Please DO NOT translate the word "BridgeDB".
-#: bridgedb/strings.py:53
-msgid "Welcome to BridgeDB!"
-msgstr ""
-
-#. TRANSLATORS: Please DO NOT translate the words "transport" or "TYPE".
-#: bridgedb/strings.py:55
-msgid "Currently supported transport TYPEs:"
-msgstr ""
-
-#: bridgedb/strings.py:56
-#, python-format
-msgid "Hey, %s!"
-msgstr ""
-
-#: bridgedb/strings.py:57
-msgid "Hello, friend!"
-msgstr ""
-
-#: bridgedb/distributors/https/templates/base.html:102 bridgedb/strings.py:58
-msgid "Public Keys"
-msgstr ""
-
-#. TRANSLATORS: This string will end up saying something like:
-#. "This email was generated with rainbows, unicorns, and sparkles
-#. for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39."
-#: bridgedb/strings.py:62
-#, python-format
+#: bridgedb/strings.py:49
msgid ""
-"This email was generated with rainbows, unicorns, and sparkles\n"
-"for %s on %s at %s."
+"If these bridges are not what you need, reply to this email with one of\n"
+"the following commands in the message body:"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
#. TRANSLATORS: Please DO NOT translate "Tor".
#. TRANSLATORS: Please DO NOT translate "Tor Network".
-#: bridgedb/strings.py:72
+#: bridgedb/strings.py:59
#, python-format
msgid ""
"BridgeDB can provide bridges with several %stypes of Pluggable Transports%s,\n"
@@ -245,7 +218,7 @@ msgid ""
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
-#: bridgedb/strings.py:79
+#: bridgedb/strings.py:66
msgid ""
"Some bridges with IPv6 addresses are also available, though some Pluggable\n"
"Transports aren't IPv6 compatible.\n"
@@ -257,7 +230,7 @@ msgstr ""
#. regular, or unexciting". Like vanilla ice cream. It refers to bridges
#. which do not have Pluggable Transports, and only speak the regular,
#. boring Tor protocol. Translate it as you see fit. Have fun with it.
-#: bridgedb/strings.py:88
+#: bridgedb/strings.py:75
#, python-format
msgid ""
"Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any"
@@ -268,21 +241,21 @@ msgid ""
"\n"
msgstr ""
-#: bridgedb/strings.py:101 bridgedb/test/test_https.py:356
+#: bridgedb/strings.py:87 bridgedb/test/test_https.py:356
msgid "What are bridges?"
msgstr ""
-#: bridgedb/strings.py:102
+#: bridgedb/strings.py:88
#, python-format
msgid "%s Bridges %s are Tor relays that help you circumvent censorship."
msgstr ""
-#: bridgedb/strings.py:107
+#: bridgedb/strings.py:93
msgid "I need an alternative way of getting bridges!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "get transport obfs4".
-#: bridgedb/strings.py:109
+#: bridgedb/strings.py:95
#, python-format
msgid ""
"Another way to get bridges is to send an email to %s. Leave the email subject"
@@ -294,32 +267,32 @@ msgid ""
"providers: %s or %s."
msgstr ""
-#: bridgedb/strings.py:117
+#: bridgedb/strings.py:103
msgid "My bridges don't work! I need help!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
#. TRANSLATORS: The two '%s' are substituted with "Tor Browser Manual" and
#. "Support Portal", respectively.
-#: bridgedb/strings.py:121
+#: bridgedb/strings.py:107
#, python-format
msgid "If your Tor Browser cannot connect, please take a look at the %s and our %s."
msgstr ""
-#: bridgedb/strings.py:125
+#: bridgedb/strings.py:111
msgid "Here are your bridge lines:"
msgstr ""
-#: bridgedb/strings.py:126
+#: bridgedb/strings.py:112
msgid "Get Bridges!"
msgstr ""
-#: bridgedb/strings.py:130
+#: bridgedb/strings.py:116
msgid "Bridge distribution mechanisms"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB", "HTTPS", and "Moat".
-#: bridgedb/strings.py:132
+#: bridgedb/strings.py:118
#, python-format
msgid ""
"BridgeDB implements four mechanisms to distribute bridges: \"HTTPS\", "
@@ -333,7 +306,7 @@ msgid ""
"mechanisms is."
msgstr ""
-#: bridgedb/strings.py:138
+#: bridgedb/strings.py:124
#, python-format
msgid ""
"The \"HTTPS\" distribution mechanism hands out bridges over this website. To"
@@ -343,7 +316,7 @@ msgid ""
"solve the subsequent CAPTCHA."
msgstr ""
-#: bridgedb/strings.py:142
+#: bridgedb/strings.py:128
#, python-format
msgid ""
"The \"Moat\" distribution mechanism is part of Tor Browser, allowing users to"
@@ -356,7 +329,7 @@ msgid ""
"bridges."
msgstr ""
-#: bridgedb/strings.py:148
+#: bridgedb/strings.py:134
#, python-format
msgid ""
"Users can request bridges from the \"Email\" distribution mechanism by "
@@ -366,11 +339,11 @@ msgid ""
"email body."
msgstr ""
-#: bridgedb/strings.py:152
+#: bridgedb/strings.py:138
msgid "Reserved"
msgstr ""
-#: bridgedb/strings.py:153
+#: bridgedb/strings.py:139
#, python-format
msgid ""
"BridgeDB maintains a small number of bridges that are not distributed\n"
@@ -384,11 +357,11 @@ msgid ""
"called \"Unallocated\" in %sbridge pool assignment%s files."
msgstr ""
-#: bridgedb/strings.py:160
+#: bridgedb/strings.py:146
msgid "None"
msgstr ""
-#: bridgedb/strings.py:161
+#: bridgedb/strings.py:147
msgid ""
"Bridges whose distribution mechanism is \"None\" are not distributed by "
"BridgeDB.\n"
@@ -399,33 +372,33 @@ msgid ""
"it will then change to the bridge's actual distribution mechanism.\n"
msgstr ""
-#: bridgedb/strings.py:171
+#: bridgedb/strings.py:157
msgid "Please select options for bridge type:"
msgstr ""
-#: bridgedb/strings.py:172
+#: bridgedb/strings.py:158
msgid "Do you need IPv6 addresses?"
msgstr ""
-#: bridgedb/strings.py:173
+#: bridgedb/strings.py:159
#, python-format
msgid "Do you need a %s?"
msgstr ""
-#: bridgedb/strings.py:177
+#: bridgedb/strings.py:163
msgid "Your browser is not displaying images properly."
msgstr ""
-#: bridgedb/strings.py:178
+#: bridgedb/strings.py:164
msgid "Enter the characters from the image above..."
msgstr ""
-#: bridgedb/strings.py:182
+#: bridgedb/strings.py:168
msgid "How to start using your bridges"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
-#: bridgedb/strings.py:184
+#: bridgedb/strings.py:170
#, python-format
msgid ""
" First, you need to %sdownload Tor Browser%s. Our Tor Browser User\n"
@@ -434,29 +407,29 @@ msgid ""
" are using Android, %sclick here%s."
msgstr ""
-#: bridgedb/strings.py:192
-msgid "Displays this message."
+#: bridgedb/strings.py:175
+msgid ""
+"Add these bridges to your Tor Browser by opening your browser\n"
+"preferences, clicking on \"Tor\", and then adding them to the \"Provide a\n"
+"bridge\" field."
msgstr ""
-#. TRANSLATORS: Please try to make it clear that "vanilla" here refers to the
-#. same non-Pluggable Transport bridges described above as being
-#. "plain-ol'-vanilla" bridges.
-#: bridgedb/strings.py:196
-msgid "Request vanilla bridges."
+#: bridgedb/strings.py:182
+msgid "(Request unobfuscated Tor bridges.)"
msgstr ""
-#: bridgedb/strings.py:197
-msgid "Request IPv6 bridges."
+#: bridgedb/strings.py:183
+msgid "(Request IPv6 bridges.)"
msgstr ""
-#. TRANSLATORS: Please DO NOT translate the word the word "TYPE".
-#: bridgedb/strings.py:199
-msgid "Request a Pluggable Transport by TYPE."
+#. TRANSLATORS: Please DO NOT translate the word "TYPE".
+#: bridgedb/strings.py:185
+msgid "(Request obfuscated bridges. Replace TYPE with 'obfs4'.)"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "GnuPG".
-#: bridgedb/strings.py:202
-msgid "Get a copy of BridgeDB's public GnuPG key."
+#: bridgedb/strings.py:189
+msgid "(Get a copy of BridgeDB's public GnuPG key.)"
msgstr ""
diff --git a/bridgedb/metrics.py b/bridgedb/metrics.py
index bb888d9..48713f0 100644
--- a/bridgedb/metrics.py
+++ b/bridgedb/metrics.py
@@ -22,7 +22,6 @@ import datetime
from bridgedb import geo
from bridgedb.distributors.common.http import getClientIP
from bridgedb.distributors.email import request
-from bridgedb.distributors.email.distributor import EmailRequestedHelp
from twisted.mail.smtp import Address
@@ -387,11 +386,7 @@ class EmailMetrics(Metrics):
emailAddr = emailAddrs[0]
# Get the requested transport protocol.
- try:
- br = request.determineBridgeRequestOptions(
- smtpAutoresp.incoming.lines)
- except EmailRequestedHelp:
- return
+ br = request.determineBridgeRequestOptions( smtpAutoresp.incoming.lines)
bridgeType = "vanilla" if not len(br.transports) else br.transports[0]
# Over email, transports are requested by typing them. Typos happen
diff --git a/bridgedb/strings.py b/bridgedb/strings.py
index b6a7f1f..f3ea849 100644
--- a/bridgedb/strings.py
+++ b/bridgedb/strings.py
@@ -38,30 +38,17 @@ def _(text):
return text
-# TRANSLATORS: Please do not translate the word "TYPE".
EMAIL_MISC_TEXT = {
0: _("""\
-[This is an automated message; please do not reply.]"""),
+[This is an automated email.]"""),
1: _("""\
Here are your bridges:"""),
2: _("""\
You have exceeded the rate limit. Please slow down! The minimum time between
emails is %s hours. All further emails during this time period will be ignored."""),
3: _("""\
-COMMANDs: (combine COMMANDs to specify multiple options simultaneously)"""),
- # TRANSLATORS: Please DO NOT translate the word "BridgeDB".
- 4: _("Welcome to BridgeDB!"),
- # TRANSLATORS: Please DO NOT translate the words "transport" or "TYPE".
- 5: _("Currently supported transport TYPEs:"),
- 6: _("Hey, %s!"),
- 7: _("Hello, friend!"),
- 8: _("Public Keys"),
- # TRANSLATORS: This string will end up saying something like:
- # "This email was generated with rainbows, unicorns, and sparkles
- # for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39."
- 9: _("""\
-This email was generated with rainbows, unicorns, and sparkles
-for %s on %s at %s."""),
+If these bridges are not what you need, reply to this email with one of
+the following commands in the message body:"""),
}
WELCOME = {
@@ -90,11 +77,10 @@ Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any
Pluggable Transports %s which maybe doesn't sound as cool, but they can still
help to circumvent internet censorship in many cases.\n\n"""),
}
-"""These strings should go on the first "Welcome" email sent by the
-:mod:`~bridgedb.EmailServer`, as well as on the ``index.html`` template used
-by the :mod:`~bridgedb.distributors.https.server`. They are used as an introduction to
-explain what Tor bridges are, what bridges do, and why someone might want to
-use bridges.
+"""These strings should go on the ``options.html`` template used by the
+:mod:`~bridgedb.distributors.https.server`. They are used as an
+introduction to explain what Tor bridges are, what bridges do, and why
+someone might want to use bridges.
"""
FAQ = {
@@ -186,22 +172,21 @@ HOWTO_TBB = {
Manual explains how you can add your bridges to Tor Browser. If you are
using Windows, Linux, or OS X, %sclick here%s to learn more. If you
are using Android, %sclick here%s."""),
+ 2: _("""\
+Add these bridges to your Tor Browser by opening your browser
+preferences, clicking on "Tor", and then adding them to the "Provide a
+bridge" field."""),
}
EMAIL_COMMANDS = {
- "get help": _("Displays this message."),
-# TRANSLATORS: Please try to make it clear that "vanilla" here refers to the
-# same non-Pluggable Transport bridges described above as being
-# "plain-ol'-vanilla" bridges.
- "get bridges": _("Request vanilla bridges."),
- "get ipv6": _("Request IPv6 bridges."),
- # TRANSLATORS: Please DO NOT translate the word the word "TYPE".
- "get transport [TYPE]": _("Request a Pluggable Transport by TYPE."),
+ "get bridges": _("(Request unobfuscated Tor bridges.)"),
+ "get ipv6": _("(Request IPv6 bridges.)"),
+ # TRANSLATORS: Please DO NOT translate the word "TYPE".
+ "get transport TYPE": _("(Request obfuscated bridges. Replace TYPE with "
+ "'obfs4'.)"),
# TRANSLATORS: Please DO NOT translate "BridgeDB".
# TRANSLATORS: Please DO NOT translate "GnuPG".
- "get key": _("Get a copy of BridgeDB's public GnuPG key."),
- #"subscribe": _("Subscribe to receive new bridges once per week"),
- #"unsubscribe": _("Cancel a subscription to new bridges"),
+ "get key": _("(Get a copy of BridgeDB's public GnuPG key.)"),
}
#-----------------------------------------------------------------------------
diff --git a/bridgedb/test/test_email_autoresponder.py b/bridgedb/test/test_email_autoresponder.py
index c8e9624..d5023e0 100644
--- a/bridgedb/test/test_email_autoresponder.py
+++ b/bridgedb/test/test_email_autoresponder.py
@@ -70,11 +70,12 @@ class CreateResponseBodyTests(unittest.TestCase):
self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', ret)
def test_createResponseBody_bridges_invalid(self):
- """An invalid request for 'transport obfs3' should get help text."""
+ """An invalid request for 'transport obfs3' should still return
+ bridges."""
lines = self._getIncomingLines("testing@localhost")
lines[4] = "transport obfs3"
ret = autoresponder.createResponseBody(lines, self.ctx, self.toAddress)
- self.assertSubstring("COMMANDs", ret)
+ self.assertSubstring("Here are your bridges:", ret)
def test_createResponseBody_bridges_obfs3(self):
"""A request for 'get transport obfs3' should receive a response."""
diff --git a/bridgedb/test/test_email_request.py b/bridgedb/test/test_email_request.py
index 0c87d36..e0bb642 100644
--- a/bridgedb/test/test_email_request.py
+++ b/bridgedb/test/test_email_request.py
@@ -17,26 +17,25 @@ import ipaddr
from twisted.trial import unittest
+from bridgedb import strings
from bridgedb.distributors.email import request
class DetermineBridgeRequestOptionsTests(unittest.TestCase):
"""Unittests for :func:`b.e.request.determineBridgeRequestOptions`."""
- def test_determineBridgeRequestOptions_get_help(self):
- """Requesting 'get help' should raise EmailRequestedHelp."""
- lines = ['',
- 'get help']
- self.assertRaises(request.EmailRequestedHelp,
- request.determineBridgeRequestOptions, lines)
-
- def test_determineBridgeRequestOptions_get_halp(self):
- """Requesting 'get halp' should raise EmailRequestedHelp."""
+ def test_determineBridgeRequestOptions_multiline_invalid(self):
lines = ['',
- 'get halp']
- self.assertRaises(request.EmailRequestedHelp,
- request.determineBridgeRequestOptions, lines)
-
+ 'help',
+ 'i need bridges',
+ 'give me your gpgs']
+ reqvest = request.determineBridgeRequestOptions(lines)
+ # We consider every request valid...
+ self.assertEqual(reqvest.isValid(), True)
+ self.assertFalse(reqvest.wantsKey())
+ # ...so by default, we return a bridge.
+ self.assertEqual(len(reqvest.transports), 1)
+
def test_determineBridgeRequestOptions_get_key(self):
"""Requesting 'get key' should raise EmailRequestedKey."""
lines = ['',
@@ -45,14 +44,14 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
request.determineBridgeRequestOptions, lines)
def test_determineBridgeRequestOptions_multiline_invalid(self):
- """Requests without a 'get' anywhere should be considered invalid."""
+ """Requests without a 'get' are incorrect but still valid, and should
+ return bridges."""
lines = ['',
'transport obfs3',
'ipv6 vanilla bridges',
'give me your gpgs']
reqvest = request.determineBridgeRequestOptions(lines)
- # It's invalid because it didn't include a 'get' anywhere.
- self.assertEqual(reqvest.isValid(), False)
+ self.assertEqual(reqvest.isValid(), True)
self.assertFalse(reqvest.wantsKey())
# Though they did request IPv6, technically.
self.assertIs(reqvest.ipVersion, 6)
@@ -61,9 +60,8 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
self.assertEqual(reqvest.transports[0], 'obfs3')
def test_determineBridgeRequestOptions_multiline_valid(self):
- """Though requests with a 'get' are considered valid."""
lines = ['',
- 'get transport obfs3',
+ 'transport obfs3',
'vanilla bridges',
'transport scramblesuit unblocked ca']
reqvest = request.determineBridgeRequestOptions(lines)
@@ -73,6 +71,7 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
# Though they didn't request IPv6, so it should default to IPv4.
self.assertIs(reqvest.ipVersion, 4)
# And they requested two transports.
+ print(reqvest.transports)
self.assertEqual(len(reqvest.transports), 2)
self.assertEqual(reqvest.transports[0], 'obfs3')
self.assertEqual(reqvest.transports[1], 'scramblesuit')
@@ -103,13 +102,16 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
self.assertEqual(reqvest.notBlockedIn[0], 'ca')
def test_determineBridgeRequestOptions_get_transport(self):
- """An invalid request for 'transport obfs3' (missing the 'get')."""
+ """An invalid request for 'transprot obfs3' (typo) should return our
+ default bridge."""
+ default_transport = "obfs4"
+ strings._setDefaultTransport(default_transport)
lines = ['',
- 'transport obfs3']
+ 'transprot obfs3']
reqvest = request.determineBridgeRequestOptions(lines)
self.assertEqual(len(reqvest.transports), 1)
- self.assertEqual(reqvest.transports[0], 'obfs3')
- self.assertEqual(reqvest.isValid(), False)
+ self.assertEqual(reqvest.transports[0], default_transport)
+ self.assertEqual(reqvest.isValid(), True)
def test_determineBridgeRequestOptions_get_ipv6(self):
"""An valid request for 'get ipv6'."""
diff --git a/bridgedb/test/test_email_templates.py b/bridgedb/test/test_email_templates.py
index 1d55dd9..4a5979d 100644
--- a/bridgedb/test/test_email_templates.py
+++ b/bridgedb/test/test_email_templates.py
@@ -36,7 +36,7 @@ class EmailTemplatesTests(unittest.TestCase):
self.offlineFingerprint = '7B78437015E63DF47BB1270ACBD97AA24E8E472E'
def shouldIncludeCommands(self, text):
- self.assertSubstring('COMMANDs', text)
+ self.assertSubstring('commands', text)
def shouldIncludeInstructions(self, text):
self.assertSubstring('Tor Browser', text)
@@ -46,10 +46,10 @@ class EmailTemplatesTests(unittest.TestCase):
self.assertSubstring('Here are your bridges:', text)
def shouldIncludeGreeting(self, text):
- self.assertSubstring('Hey, blackhole!', text)
+ self.assertSubstring('This is an automated email', text)
def shouldIncludeAutomationNotice(self, text):
- self.assertSubstring('automated message', text)
+ self.assertSubstring('automated email', text)
def shouldIncludeKey(self, text):
self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', text)
@@ -59,26 +59,9 @@ class EmailTemplatesTests(unittest.TestCase):
self.shouldIncludeCommands(text)
def test_templates_addGreeting(self):
- text = templates.addGreeting(self.t, self.client.local)
+ text = templates.addGreeting(self.t)
self.shouldIncludeGreeting(text)
- def test_templates_addGreeting_noClient(self):
- text = templates.addGreeting(self.t, None)
- self.assertSubstring('Hello, friend!', text)
-
- def test_templates_addGreeting_withWelcome(self):
- text = templates.addGreeting(self.t, self.client.local, welcome=True)
- self.shouldIncludeGreeting(text)
- self.assertSubstring('Welcome to BridgeDB!', text)
-
- def test_templates_addGreeting_trueClient(self):
- text = templates.addGreeting(self.t, True)
- self.assertSubstring('Hey', text)
-
- def test_templates_addGreeting_23Client(self):
- text = templates.addGreeting(self.t, 23)
- self.assertSubstring('Hey', text)
-
def test_templates_addHowto(self):
text = templates.addHowto(self.t)
self.shouldIncludeInstructions(text)
@@ -97,12 +80,6 @@ class EmailTemplatesTests(unittest.TestCase):
text = templates.buildKeyMessage(self.t, self.client)
self.assertSubstring(self.offlineFingerprint, text)
- def test_templates_buildWelcomeText(self):
- text = templates.buildWelcomeText(self.t, self.client)
- self.shouldIncludeGreeting(text)
- self.assertSubstring('Welcome to BridgeDB!', text)
- self.shouldIncludeCommands(text)
-
def test_templates_buildSpamWarning(self):
text = templates.buildSpamWarning(self.t, self.client)
self.shouldIncludeGreeting(text)
1
0

27 May '20
commit bca64964a255cf959489c7049c66e5eb70b5291c
Merge: 7afbe7e 1958bbb
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 15:30:12 2020 -0700
Merge branch 'defect/30941' into develop
CHANGELOG | 6 ++
bridgedb/distributors/email/autoresponder.py | 10 --
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 20 ++--
bridgedb/distributors/email/templates.py | 126 +++++------------------
bridgedb/i18n/templates/bridgedb.pot | 143 +++++++++++----------------
bridgedb/metrics.py | 7 +-
bridgedb/strings.py | 49 ++++-----
bridgedb/test/test_email_autoresponder.py | 5 +-
bridgedb/test/test_email_request.py | 46 ++++-----
bridgedb/test/test_email_templates.py | 41 +-------
11 files changed, 151 insertions(+), 308 deletions(-)
1
0

[bridgedb/master] Give BridgeDB more time to start before unit test.
by phw@torproject.org 27 May '20
by phw@torproject.org 27 May '20
27 May '20
commit 8105032e2ab876d1c7d31471b828a0690f2bf6f3
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 09:41:45 2020 -0700
Give BridgeDB more time to start before unit test.
The renaming of test_Bridges.py to test_bridgerings.py means that
test_bridgedb_script.py is now run earlier (because tests are executed
in alphabetic order), which means less time for BridgeDB to start. This
commit adds an extra sleep to a unit test, so we can be reasonably sure
that BridgeDB is already running when unlinking its assignments file.
---
bridgedb/test/test_bridgedb_script.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/bridgedb/test/test_bridgedb_script.py b/bridgedb/test/test_bridgedb_script.py
index 76b4001..b58e016 100644
--- a/bridgedb/test/test_bridgedb_script.py
+++ b/bridgedb/test/test_bridgedb_script.py
@@ -79,6 +79,7 @@ class BridgeDBCliTest(unittest.TestCase):
if not self.pid or not processExists(self.pid):
raise SkipTest("Can't run test: no BridgeDB process running.")
+ self.doSleep()
os.unlink(self.assignmentsFile)
os.kill(self.pid, signal.SIGHUP)
self.doSleep()
1
0

27 May '20
commit 7afbe7e2866c7628bc5e40b15618105843486c80
Merge: 2ccf7ef 8105032
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Apr 6 10:24:31 2020 -0700
Merge branch 'defect/29686' into develop
CHANGELOG | 4 ++++
bridgedb/{Bridges.py => bridgerings.py} | 4 ++--
bridgedb/bridges.py | 4 ++--
bridgedb/distributors/email/distributor.py | 8 ++++----
bridgedb/distributors/https/distributor.py | 11 ++++++-----
bridgedb/distributors/moat/distributor.py | 5 +++--
bridgedb/main.py | 18 +++++++++---------
bridgedb/persistent.py | 11 +++++++----
bridgedb/test/deprecated.py | 4 ++--
bridgedb/test/legacy_Tests.py | 12 ++++++------
bridgedb/test/test_Tests.py | 10 +++++-----
bridgedb/test/test_bridgedb_script.py | 2 ++
.../test/{test_Bridges.py => test_bridgerings.py} | 22 +++++++++++-----------
bridgedb/test/test_bridges.py | 12 ++++++------
bridgedb/test/test_https_distributor.py | 4 ++--
bridgedb/test/util.py | 4 ++--
doc/sphinx/ext/traclinks.py | 3 ++-
...idgedb.Bridges.rst => bridgedb.bridgerings.rst} | 6 +++---
doc/sphinx/source/bridgedb.rst | 2 +-
doc/sphinx/source/conf.py | 2 +-
20 files changed, 80 insertions(+), 68 deletions(-)
1
0
commit bcfe39f5f04adfed266490e523fe6d5e9b585047
Author: Philipp Winter <phw(a)nymity.ch>
Date: Fri Mar 27 13:16:01 2020 -0700
Remove silly email footer.
---
bridgedb/distributors/email/templates.py | 43 --------------------------------
bridgedb/test/test_email_templates.py | 10 --------
2 files changed, 53 deletions(-)
diff --git a/bridgedb/distributors/email/templates.py b/bridgedb/distributors/email/templates.py
index 570341a..d618c37 100644
--- a/bridgedb/distributors/email/templates.py
+++ b/bridgedb/distributors/email/templates.py
@@ -102,45 +102,8 @@ def addHowto(template):
howToTBB += u'\n\n'
return howToTBB
-def addFooter(template, clientAddress=None):
- """Add a footer::
-
- --
- <3 BridgeDB
- ________________________________________________________________________
- Public Keys: https://bridges.torproject.org/keys
-
- This email was generated with rainbows, unicorns, and sparkles
- for alice(a)example.com on Friday, 09 May, 2014 at 18:59:39.
-
-
- :type template: ``gettext.NullTranslation`` or ``gettext.GNUTranslation``
- :param template: A gettext translations instance, optionally with fallback
- languages set.
- :type clientAddress: :api:`twisted.mail.smtp.Address`
- :param clientAddress: The client's email address which should be in the
- ``To:`` header of the response email.
- """
- now = datetime.utcnow()
- clientAddr = clientAddress.addrstr
-
- footer = u' --\n'
- footer += u' <3 BridgeDB\n'
- footer += u'_' * 70
- footer += u'\n'
- footer += template.gettext(strings.EMAIL_MISC_TEXT[8])
- footer += u': https://bridges.torproject.org/keys\n'
- footer += template.gettext(strings.EMAIL_MISC_TEXT[9]) \
- % (clientAddr,
- now.strftime('%A, %d %B, %Y'),
- now.strftime('%H:%M:%S'))
- footer += u'\n\n'
-
- return footer
-
def buildKeyMessage(template, clientAddress=None):
message = addKeyfile(template)
- message += addFooter(template, clientAddress)
return message
def buildWelcomeText(template, clientAddress=None):
@@ -159,8 +122,6 @@ def buildWelcomeText(template, clientAddress=None):
message = u"\n\n".join(sections)
# Add the markdown links at the end:
message += strings.EMAIL_REFERENCE_LINKS.get("WELCOME0")
- message += u"\n\n"
- message += addFooter(template, clientAddress)
return message
@@ -171,8 +132,6 @@ def buildAnswerMessage(template, clientAddress=None, answer=None):
message += addHowto(template)
message += u'\n\n'
message += addCommands(template)
- message += u'\n\n'
- message += addFooter(template, clientAddress)
except Exception as error: # pragma: no cover
logging.error("Error while formatting email message template:")
logging.exception(error)
@@ -187,8 +146,6 @@ def buildSpamWarning(template, clientAddress=None):
message += u"\n\n"
message += template.gettext(strings.EMAIL_MISC_TEXT[2]) \
% str(MAX_EMAIL_RATE / 3600)
- message += u"\n\n"
- message += addFooter(template, clientAddress)
except Exception as error: # pragma: no cover
logging.error("Error while formatting email spam template:")
logging.exception(error)
diff --git a/bridgedb/test/test_email_templates.py b/bridgedb/test/test_email_templates.py
index 4703019..1d55dd9 100644
--- a/bridgedb/test/test_email_templates.py
+++ b/bridgedb/test/test_email_templates.py
@@ -54,9 +54,6 @@ class EmailTemplatesTests(unittest.TestCase):
def shouldIncludeKey(self, text):
self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', text)
- def shouldIncludeFooter(self, text):
- self.assertSubstring('rainbows, unicorns, and sparkles', text)
-
def test_templates_addCommands(self):
text = templates.addCommands(self.t)
self.shouldIncludeCommands(text)
@@ -90,16 +87,11 @@ class EmailTemplatesTests(unittest.TestCase):
text = templates.addBridgeAnswer(self.t, self.answer)
self.shouldIncludeBridges(text)
- def test_templates_addFooter(self):
- text = templates.addFooter(self.t, self.client)
- self.shouldIncludeFooter(text)
-
def test_templates_buildAnswerMessage(self):
text = templates.buildAnswerMessage(self.t, self.client, self.answer)
self.assertSubstring(self.answer, text)
self.shouldIncludeAutomationNotice(text)
self.shouldIncludeCommands(text)
- self.shouldIncludeFooter(text)
def test_templates_buildKeyMessage(self):
text = templates.buildKeyMessage(self.t, self.client)
@@ -110,10 +102,8 @@ class EmailTemplatesTests(unittest.TestCase):
self.shouldIncludeGreeting(text)
self.assertSubstring('Welcome to BridgeDB!', text)
self.shouldIncludeCommands(text)
- self.shouldIncludeFooter(text)
def test_templates_buildSpamWarning(self):
text = templates.buildSpamWarning(self.t, self.client)
self.shouldIncludeGreeting(text)
self.shouldIncludeAutomationNotice(text)
- self.shouldIncludeFooter(text)
1
0

27 May '20
commit 8b4a087cc2278883e1383ac786ebdee74adcd548
Author: Philipp Winter <phw(a)nymity.ch>
Date: Tue Apr 7 10:15:29 2020 -0700
Simplify command for requesting obfs4 bridges.
Thanks to Roger for suggesting this.
---
bridgedb/i18n/templates/bridgedb.pot | 11 +++++------
bridgedb/strings.py | 4 +---
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/bridgedb/i18n/templates/bridgedb.pot b/bridgedb/i18n/templates/bridgedb.pot
index 65f8ca6..85958bd 100644
--- a/bridgedb/i18n/templates/bridgedb.pot
+++ b/bridgedb/i18n/templates/bridgedb.pot
@@ -5,11 +5,11 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: bridgedb 0.10.0+8.g97621c0\n"
+"Project-Id-Version: bridgedb 0.10.0+7.gbca6496.dirty\n"
"Report-Msgid-Bugs-To: "
"'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…"
"=bridgedb-reported,msgid&cc=isis,sysrqb&owner=isis'\n"
-"POT-Creation-Date: 2020-04-06 13:53-0700\n"
+"POT-Creation-Date: 2020-04-07 10:14-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL(a)li.org>\n"
@@ -422,14 +422,13 @@ msgstr ""
msgid "(Request IPv6 bridges.)"
msgstr ""
-#. TRANSLATORS: Please DO NOT translate the word "TYPE".
-#: bridgedb/strings.py:185
-msgid "(Request obfuscated bridges. Replace TYPE with 'obfs4'.)"
+#: bridgedb/strings.py:184
+msgid "(Request obfs4 obfuscated bridges.)"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB".
#. TRANSLATORS: Please DO NOT translate "GnuPG".
-#: bridgedb/strings.py:189
+#: bridgedb/strings.py:187
msgid "(Get a copy of BridgeDB's public GnuPG key.)"
msgstr ""
diff --git a/bridgedb/strings.py b/bridgedb/strings.py
index f3ea849..6bccf81 100644
--- a/bridgedb/strings.py
+++ b/bridgedb/strings.py
@@ -181,9 +181,7 @@ bridge" field."""),
EMAIL_COMMANDS = {
"get bridges": _("(Request unobfuscated Tor bridges.)"),
"get ipv6": _("(Request IPv6 bridges.)"),
- # TRANSLATORS: Please DO NOT translate the word "TYPE".
- "get transport TYPE": _("(Request obfuscated bridges. Replace TYPE with "
- "'obfs4'.)"),
+ "get transport obfs4": _("(Request obfs4 obfuscated bridges.)"),
# TRANSLATORS: Please DO NOT translate "BridgeDB".
# TRANSLATORS: Please DO NOT translate "GnuPG".
"get key": _("(Get a copy of BridgeDB's public GnuPG key.)"),
1
0
commit 2ae19e5c25dca6acdb0307c147dc93f73e257f7e
Author: hiro <hiro(a)torproject.org>
Date: Mon Oct 21 19:54:50 2019 +0200
Add service status check
---
scripts/check_status | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 137 insertions(+)
diff --git a/scripts/check_status b/scripts/check_status
new file mode 100644
index 0000000..8f8f3e5
--- /dev/null
+++ b/scripts/check_status
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# This file is part of BridgeDB, a Tor bridge distribution system.
+#
+# :authors: hiro <hiro(a)torproject.org>
+# see also AUTHORS file
+#
+# :license: This is Free Software. See LICENSE for license information.
+
+import sys
+import smtplib
+import time
+import imaplib
+import email
+import time
+
+# Standard Nagios return codes
+OK, WARNING, CRITICAL, UNKNOWN = range(4)
+
+ORG_EMAIL = "@gmail.com"
+FROM_EMAIL = "test.bridges.browser" + ORG_EMAIL
+SMTP_SERVER = "imap.gmail.com"
+SMTP_PORT = 993
+
+MESSAGE_FROM = "bridges(a)torproject.org"
+MESSAGE_SUBJECT = "Bridges"
+MESSAGE_BODY = ":443"
+
+STATUS_FILE = "/srv/bridgedb.torproject.org/check/status"
+
+# -------------------------------------------------
+#
+# Utility to read email from Gmail Using Python
+#
+# ------------------------------------------------
+
+def test_email_from_gmail(password):
+ try:
+ mail = imaplib.IMAP4_SSL(SMTP_SERVER)
+ mail.login(FROM_EMAIL, password)
+ mail.select('INBOX')
+
+ type, data = mail.search(None, 'ALL')
+ mail_ids = data[0]
+
+ id_list = mail_ids.split()
+ first_email_id = int(str(id_list[0], 'utf-8'))
+ latest_email_id = int(str(id_list[-1], 'utf-8'))
+
+ for i in range(int(latest_email_id), int(first_email_id), -1):
+ typ, data = mail.fetch(str(i), '(RFC822)')
+
+ for response_part in data:
+ if isinstance(response_part, tuple):
+ m = str(response_part[1], 'utf-8')
+ msg = email.message_from_string(m)
+ email_subject = "{}".format(msg['subject'])
+ email_from = "{}".format(msg['from'])
+ email_body = "{}".format(msg.as_string())
+
+ if (MESSAGE_FROM == email_from) and (MESSAGE_SUBJECT == email_subject) and (MESSAGE_BODY in email_body):
+ mail.store(str(i), '+FLAGS', '\\Deleted')
+ mail.close()
+ return OK, "Bridgedb is good and sending emails with working bridges"
+ else:
+ mail.store(str(i), '+FLAGS', '\\Deleted')
+
+ mail.close()
+ return WARNING, "No emails from gettor found"
+
+ except Exception as e:
+ return CRITICAL, str(e)
+
+def send_email_from_gmail(password):
+ sent_from = FROM_EMAIL
+ sent_to = ["{}".format(MESSAGE_FROM)]
+ subject = 'Bridges'
+ body = 'get bridges'
+
+ email_text = """From: %s\nTo: %s\nSubject: %s\n\n%s""" % (sent_from, ", ".join(sent_to), subject, body)
+
+ try:
+ mail = smtplib.SMTP_SSL('smtp.gmail.com', 465)
+ mail.ehlo()
+ mail.login(sent_from, password)
+ mail.sendmail(sent_from, sent_to, email_text)
+ mail.close()
+ return OK, "Test email sent"
+ except Exception as e:
+ return UNKNOWN, str(e)
+
+ if __name__ == "__main__":
+ status, message = None, None
+
+ if len(sys.argv) == 2:
+ password = sys.argv[1]
+ else:
+ password = "yourPassword"
+
+ status_file = open(STATUS_FILE, 'r')
+ message = status_file.read()
+ status_file.close()
+
+ try:
+ status, message = send_email_from_gmail(password)
+ except Exception as e:
+ status = UNKNOWN
+ message = repr(e)
+ status_file = open(STATUS_FILE,'w')
+ status_file.write("UNKNOWN\n3: %s" % message)
+ status_file.close()
+
+ time.sleep(600)
+
+ try:
+ status, message = test_email_from_gmail(password)
+ except KeyboardInterrupt:
+ status, message = CRITICAL, "Caught Control-C..."
+ except Exception as e:
+ status = CRITICAL
+ message = repr(e)
+ finally:
+ status_file = open(STATUS_FILE,'w')
+ if status == OK:
+ status_file.write("OK\n0: %s" % message)
+ elif status == WARNING:
+ status_file.write("WARNING\n1: %s" % message)
+ elif status == CRITICAL:
+ status_file.write("CRITICAL\n2: %s" % message)
+ else:
+ status_file.write("UNKNOWN\n3: %s" % message)
+ status = UNKNOWN
+
+ status_file.close()
+
+ sys.exit(status)
1
0

27 May '20
commit 208b49cd91ec64aaff623dfeef08d352beab6785
Merge: bca6496 8b4a087
Author: Philipp Winter <phw(a)nymity.ch>
Date: Tue Apr 7 10:33:22 2020 -0700
Merge branch 'defect/30941' into develop
bridgedb/i18n/templates/bridgedb.pot | 11 +++++------
bridgedb/strings.py | 4 +---
2 files changed, 6 insertions(+), 9 deletions(-)
1
0
commit b366bb4af8786ca06437f7f7ce5e340c69f0f6e4
Author: Philipp Winter <phw(a)nymity.ch>
Date: Mon Oct 14 20:49:03 2019 -0700
Remove PGP support.
---
.gnupg/TESTING.pub | Bin 4622 -> 0 bytes
.gnupg/TESTING.subkeys.sec | Bin 7212 -> 0 bytes
.gnupg/bridgedb-offline-key.pub.asc | 113 ----------
.gnupg/bridgedb-online-key.pub.asc | 100 ---------
.gnupg/gpg.conf | 96 ---------
.gnupg/pubring.gpg | Bin 4634 -> 0 bytes
.gnupg/secring.gpg | Bin 7224 -> 0 bytes
.travis.requirements.txt | 1 -
CHANGELOG | 6 +
README.rst | 29 +--
bridgedb.conf | 45 ----
bridgedb/configure.py | 3 +-
bridgedb/crypto.py | 99 +--------
bridgedb/distributors/email/autoresponder.py | 41 +---
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 22 --
bridgedb/distributors/email/server.py | 10 -
bridgedb/distributors/email/templates.py | 7 -
bridgedb/distributors/https/server.py | 2 -
bridgedb/distributors/https/templates/base.html | 2 -
bridgedb/i18n/templates/bridgedb.pot | 84 ++++----
bridgedb/strings.py | 268 +-----------------------
bridgedb/test/email_helpers.py | 23 +-
bridgedb/test/test_crypto.py | 137 ------------
bridgedb/test/test_email_autoresponder.py | 15 --
bridgedb/test/test_email_request.py | 36 +---
bridgedb/test/test_email_templates.py | 11 -
bridgedb/test/test_main.py | 5 -
requirements.txt | 1 -
scripts/setup-tests | 2 +-
30 files changed, 63 insertions(+), 1101 deletions(-)
diff --git a/.gnupg/TESTING.pub b/.gnupg/TESTING.pub
deleted file mode 100644
index 764bf47..0000000
Binary files a/.gnupg/TESTING.pub and /dev/null differ
diff --git a/.gnupg/TESTING.subkeys.sec b/.gnupg/TESTING.subkeys.sec
deleted file mode 100644
index 688f7e9..0000000
Binary files a/.gnupg/TESTING.subkeys.sec and /dev/null differ
diff --git a/.gnupg/bridgedb-offline-key.pub.asc b/.gnupg/bridgedb-offline-key.pub.asc
deleted file mode 100644
index 47d1310..0000000
--- a/.gnupg/bridgedb-offline-key.pub.asc
+++ /dev/null
@@ -1,113 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-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
-ILUXBkpIDfVSoZD7qWlntai53BDQr5pfMJhv15di4XAhtqv43vAmA57ifd+QJS2U
-AfYc4CdX0lk2BZ4jRD8jCZ4Uxw15E3RqhnXsWDRxtD4fwsb2ZFi0DDuPlwBdGgh5
-Rm2Bz9JjSV6gDEuXr/JtAzjSz1Jdh8wPkSofiHGTfxysVhlGlg+YPRziRlzML8A2
-0xY+9mPxEEin5ZQ9wmrDyiiOBvPTbG3O9+Sp5VZDuD4ivW/DHumPWGVSRdjcAQDe
-HMXUVGjhBDnj06XNrgJPhODdJeYq0EnGTt15ofZQSswD7TTTRPDOn0Cz/QARAQAB
-tDpCcmlkZ2VEQiAoT2ZmbGluZSBJRCBLZXkpIDxicmlkZ2VzQGJyaWRnZXMudG9y
-cHJvamVjdC5vcmc+iQkfBBMBCgEJBQJSWQfkSBSAAAAAABcAKHZlcmlmaWVkQHRv
-cnByb2plY3Qub3JnN0I3ODQzNzAxNUU2M0RGNDdCQjEyNzBBQ0JEOTdBQTI0RThF
-NDcyRU8UgAAAAAAeAChicmlkZ2VzQGJyaWRnZXMudG9ycHJvamVjdC5vcmc3Qjc4
-NDM3MDE1RTYzREY0N0JCMTI3MEFDQkQ5N0FBMjRFOEU0NzJFKhpodHRwczovL2Jy
-aWRnZXMudG9ycHJvamVjdC5vcmcvcG9saWN5LnR4dAIbAQMLDQkEFQoJCAQWAgEA
-Ah4BAheAJxhodHRwczovL2JyaWRnZXMudG9ycHJvamVjdC5vcmcva2V5LmFzYwAK
-CRDL2XqiTo5HLoqEP/48rFpJCVStn8xo+KkHSVvsqpxDRlb/nNheI+ov2UxILdwl
-NIU6kLsvKECKPe1AHKdS/MzANbkTF35Y4QgZsNpVXaCVL7adGBSzOdPFupDJJVOu
-wa+uFRc/FuNJyH/TIn56/+R5J5C54OxIYNxvW3WF4eHKLJYk/JZOMMfy4iWm7Sql
-0nDC5O435nK4F4Jb4GLPlUIzioIy2OWqGoFHXymbGhL1tWaqasYmED4n3AMqlYw6
-xnNhdWOc/KZelPl9nanybyh0IIdZqUKZleRt4BxSgIT8FqC2sZuZ8z7O9s987Naz
-Q32SKaP4i2M9lai/Y2QYfKo+wlG+egmxtujz7etQMGlpgBZzFLdJ8/w4U11ku1ai
-om74RIn8zl/LHjMQHnCKGoVlscTI1ZPt+p+p8hO2/9vOwTR8y8O/3DQSOfTSipwc
-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
-YnJpZGdlc0BicmlkZ2VzLnRvcnByb2plY3Qub3JnREY4MTExMDlFMTdDOEJGMTM0
-QjVFRUI2OERDNDNBMjg0ODgyMUUzMioaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2pl
-Y3Qub3JnL3BvbGljeS50eHQACgkQjcQ6KEiCHjIaqBAA0BuEs7horx6iCq4cjAhv
-YPLrxuC4fKEfVyhAjCJMJSFFCPAlGgU+BjyPNDD57wzKAmUkdJG+Ss25mwWXa53w
-5R2kDqDnHocOdZGtxZ7zx/uUd2eWLNBfVuK7nHOk1d1Hs0OZBnckc+MCqnLtuYe5
-68pa9+jW6cNIjAnzMIListmoXWgYYWJvMKeBMG4DGtYJ8w7CJQjOHc5yar12DrX3
-wnQ7hXtFuuqQblpEUnLnZGvHf2NKMZfBBMcP96h9OmLGNa+vmNYsMyPKU7n5hPgX
-nTgmQ4xrv1G7JukjppZRA8SFoxupcaQeTixyWERGBhBiAbwZsbQz8L/TVZKierzg
-sdNngHcFzE8MyjuJDvTos7qXPmgSRXFqJLRn0ZxpR5V1V8BVZUqCGuSZT89TizsD
-z5vyv8c9r7HKD4pRjw32P2dgcEqyGRkqERAgSuFpObP+juty+kxYyfnadBNCyjgP
-s7u0GmsTt4CZi7BbowNRL6bynrwrmQI9LJI1bPhgqfdDUbqG3HXwHz80oRFfKou8
-JTYKxK4Iumfw2l/uAACma5ZyrwIDBX/H5XEQqch4sORzQnuhlTmZRf6ldVIIWjdJ
-ef+DpOt12s+cS2F4D5g8G6t9CprCLYyrXiHwM/U8N5ywL9IeYKSWJxa7si3l9A6o
-ZxOds8F/UJYDSIB97MQFzBo=
-=JdC7
------END PGP PUBLIC KEY BLOCK-----
diff --git a/.gnupg/bridgedb-online-key.pub.asc b/.gnupg/bridgedb-online-key.pub.asc
deleted file mode 100644
index a848a2b..0000000
--- a/.gnupg/bridgedb-online-key.pub.asc
+++ /dev/null
@@ -1,100 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQINBFIv8YABEADRqvfLB4xWj3Fz+HEmUUt/qbJnZhqIjo5WBHaBJOmrzx1c9fLN
-aYG36Hgo6A7NygI1oQmFnDinSrZAtrPaT63d1Jg49yZwr/OhMaxHYJElMFHGJ876
-kLZHmQTysquYKDHhv+fH51t7UVaZ9NkP5cI+V3pqck0DW5DwMsVJXNaU317kk9me
-mPJUDMb5FM4d2Vtk1N+54bHJgpgmnukNtpJmRyHRbZBqNMln5nWF7vdZ4u5PGPWj
-bA0rPZhayeE3FQ0MHiGL12kHAy30pfg54QfPJDQBCywjABetRE+xaM9TcS+R31Pf
-2VbLeb+Km7QpHMwOXI5xZLss9BAWm9EBbmXxuqaRBHyi830jjCrK9UYuzzOqKoUV
-Mk1BRelZTFnGPWeVTE+Ps+pwJ0Dwx4ghppJBCoArmEbkNliblxR/2wYOOFi/ZVA4
-Zc2ok9T3rBLVg07b7ezFUScGiTnc7ac7hp6r8Qsh09ZbhRr9erK/n194aEvkXTfr
-qepwrAE7YeF4YuR206UOFFWDhxWDLbRu0gIWgrevEQu/cvQPrO9uH5fL6Gw/+mNP
-Q/NIteejhkDyvyTUKyBu7x+Gls71zT2u/X13eOAJ8IxBkSVRKQ8tRD+oqJkWplOf
-+BpaGU+g6u4kT2AzFDxTOupfrYcPvORTAV/V3suys2YQE4x422GASXDivQARAQAB
-tClCcmlkZ2VEQiA8YnJpZGdlc0BicmlkZ2VzLnRvcnByb2plY3Qub3JnPokDJQQT
-AQoBD0gUgAAAAAAXACh2ZXJpZmllZEB0b3Jwcm9qZWN0Lm9yZ0RGODExMTA5RTE3
-QzhCRjEzNEI1RUVCNjhEQzQzQTI4NDg4MjFFMzJPFIAAAAAAHgAoYnJpZGdlc0Bi
-cmlkZ2VzLnRvcnByb2plY3Qub3JnREY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERD
-NDNBMjg0ODgyMUUzMioaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2plY3Qub3JnL3Bv
-bGljeS50eHQCGwEDCw0JBBUKCQgEFgIBAAIeAQIXgCcYaHR0cHM6Ly9icmlkZ2Vz
-LnRvcnByb2plY3Qub3JnL2tleS5hc2MFAlSKBKIFCQPDTiIACgkQjcQ6KEiCHjIs
-jg//bJ12eRnBMfIGzOGh+T4wz7/YyKLfARAMnqDnSxhTxuE+M5hWm3QbxP03R6eY
-x+PKwQaDJSmm7HhRhltb7QXUe8dqjnocFwwagpoLZ/81mBLxByqg5TKHGGIGy+DX
-omIzCq5ijx1IUkHlgh708a5alG7bjRTqedT4Wxxyl6psGzDhGQdS8bqx/f32nQaE
-h41l+A/EY1g2HVqky63ZHAP3S2v+mWCrk5DnkElc0229MXqaBuEr4nbYMXRkahMb
-E2gnCmdSoeD21AY6bNyz7IcJGpyKCx9+hVgPjpm3J23JEYyPL+s48jn6QcI/Q2gD
-yAtgU65y6IrdYn8SwkABI1FIq9WAwG7DaInxvkqkYqyBQLaZJEMyX8NTBvFoT5JS
-jnkxG0xu61Vxq0BLYBIOJE0VFHAJ40/jOvSxQJkQhu9G4BK7htnADbtstmMDMM3q
-xuuO5pcj2rl7YthNunyZ1yhPHXijUUyKrwR9piENpptztFBVN6+ijqU/TmWMOtbH
-X7p9F+3tXCHHqwO5U/JMtsb/9M39MR8BrdcLc7m6dCpeuSUuR2LLroh+MoMJGviI
-iesxHF95kFqkJAecW1Z3eKL9vrlbfO3waeuCi18k1TePnZuG5lmf2KjKDW5vHK4O
-WFqvvfK2kxkCUjvGdLeTOAVOV+X+PQ23jvBJO2bS7YbOb9C5Ag0EUi/ygQEQALZ/
-p7xRINHY7MMf3/bo/I0WRxWHd1AE9tRToyEg1S2u1YrWWL5M9D8saRsp9cpnpGEu
-hW3vu7G4nasY27qOz4bSKu1YMAVIC58v1tEnBqdo1zErNjhs38PrmJKbbs9tDfYY
-Oi2x0GlhMbIrNStcZpnCdLa6U6NLMbggDL1GxjMPYBMi4TtLgcIeRDUSjsZscZkg
-Kxs5QkSVc3SrYyraayIc8WtIpDLcxPt6/g90rbatZzBfO+93Rz7qUXHmgzuM0hy1
-Fvn619o3I5DsWrfOz9t/QuznoOBw4PfzDPNT7VlzZN4xHAcr5+7B+DH9IsvlCt5N
-kQFuYpFZCpXNaD2XOtmIqjTCeLNfcgTEj0qoUIEKyKbBIgfP+7S2tLXy8JKUTy5g
-9kxXQeHueLykQ4Mt18JH0nMHbHbQl0K3LGT4ucRDOmjNtlQCltVLkIk3GimyqKs/
-vdZ9c+dm4Akx1qsJcwvveX+imJe2e9RUodcxWXxWrYnuPa5b5nfR1i+GfV0on/Pt
-AQ8gc9CkJpMiq5TQDOFhFP6yQcq77sXuUkEl5qamptedz28E0I693ulnfwcsE80p
-xkpIG6n33DZJSEyqgtWjE1P2pnsVfO5ILs3mKLe7bO1v3qMXcCkMCGH/kwzvtowq
-YvY4gaZMDZtQFY8U7lI9FdRUvVdeHAB24y291nhzABEBAAGJBYMEGAEKANNIFIAA
-AAAAFwAodmVyaWZpZWRAdG9ycHJvamVjdC5vcmdERjgxMTEwOUUxN0M4QkYxMzRC
-NUVFQjY4REM0M0EyODQ4ODIxRTMyTxSAAAAAAB4AKGJyaWRnZXNAYnJpZGdlcy50
-b3Jwcm9qZWN0Lm9yZ0RGODExMTA5RTE3QzhCRjEzNEI1RUVCNjhEQzQzQTI4NDg4
-MjFFMzIqGmh0dHBzOi8vYnJpZGdlcy50b3Jwcm9qZWN0Lm9yZy9wb2xpY3kudHh0
-AhsCBQJUigTTBQkDw01SAqTB2CAEGQEKAIEFAlIv8oFPFIAAAAAAHgAoYnJpZGdl
-c0BicmlkZ2VzLnRvcnByb2plY3Qub3JnOUZFMzlEMUE3NDM4OTIyMzNCM0Y2NkYy
-MjFCNTU0RTk1OTM4RjREMCoaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2plY3Qub3Jn
-L3BvbGljeS50eHQACgkQIbVU6Vk49NDbPw/5ATe/T8+eaToC3v0TYNRH5nveQvzA
-WdnshD3lnvfsgDhbilwifKpc5LHKXU3rvb42HH2cu0ckuksdDTvICZD9cJjRq/F+
-Mzm0pNCAJg0pQnHaaWFQjw+CHYEoizai3S+iYxhNHeSdA6Ty7xm4+bHNf0Aqblbd
-6dKwq9EvjwAI6zZsAHtsmHRUMdrFwGdKae6CSchUT2JQFBPEWMhvzdpDGACWVaSP
-sxYKuYg9LgpswGcof+tprRjKRl8MtSh0ufjbVBlTeSKpL5Y+fcTRD3PI8w7Ocr3z
-jr6XpYG4SUNHsWwxyu/DTXg76Lk1/+BdaH25hDOAasLUOU7yRL8zD/c7M0FkGXdj
-r5I2DEEqwzJ9cPHWjpgb8N9fZLoPFP9JOmKGHINqxNe7TfwiTdD6uDKs/u/QK1U+
-o3iYBXBTREdopPUdBTM9wYRUhyGXTEKLhUP3MGpXYlgeYPrSdp76VyN3BzLTbMv+
-+7rxyKxL9cWYU0pnXHgPC5nyHX5nqXmhMnkxAD3Bnm8n9XDfgiyTDExqksEh2VXt
-yhVfLezylEP2fwtd8/mABBCsTjzZW6FRfRRAjUZWZGFpFg8no1x5JS9uiswRP5g1
-qHijNFWpGyTtJWl5VNd0d9+LtVUX1jRpDUpsjZcxqs3fsvw2p+H/zQ1wFvDrsoav
-hqOTq+AEnJc7ZG8JEI3EOihIgh4ych8P/3GTyWb29+43YVibbSPPvEv4gFqziC+9
-1p92FJ0V4XdaT7TW3qaZVp5edUNwB/jjF0SxBybwaMX2ZIGXOjnjF6/Zby4ynuTX
-vZkS1mKRA0KWupB3e9PSMY3ZtssnqpGna/+3qlpxtunW7HcW4nCF/f59WHhlVjaO
-MXjtuWj59yB56Dd1sNjwhcNCyp4/NpzGnRW97ZV3Pp4oqIOqcGzCQXkVPcnaqcOh
-Cs9vIDJlMtn/IWBzUGimuRllDSSVSWkYkyJcG2NUHUwgXYpLwQz7sScvmCPchf4K
-qarpX0FpkUDfqaVVuQ7A2XbPUAVFzIk930G1WzgOuOdg9vhWSEjou+SKrAoMz90w
-3xHwEvmPDTTVJQft9ytoRbwZkIPfzzhII3mr4agbORAfzDaj5g/f6CVRdg6D3ME1
-Etg9ZrfLgRY993g/arfIME6OOsiNcy5+PunN96Rw0o1xoD+97NmZuQrs/p4Mfn5o
-8EwXHutREhahin+3/SV3hz9ReeLYmClq+OVhjPzPdtwZsFoyQyUJoFVHPTuSdChZ
-FPaqN68FjlNMugmxnvski3ZDVT7pw3B6otjjaL3rr6q0PC2yhEb2ntb3IFUizHjn
-80SmfE1Bqwit7ZHu8r/Gt/0iecGk5h84VzSgiGZGF/7m1i5UMVlNSeWnsInGa5Su
-7HSzfMq+YmkzuQINBFIv8p4BEADTOLR5e5NKKRPpjCb4B/8YYkWh+orb70EogIZ6
-j5v8d/djLyhjqZ9BIkh41/hYKMwnsa4KkDkTaX0eNu3BFB2zGgZ1GSd7525ESxiq
-suXIlAg2pex7bysaFfua0nUx64tmaQm2XArdkj/wI0pbg+idWym3WQQmZLyTTbzl
-8rpTEtTt+S2m6z3EeAhEHuNFH16hEDUywlef3EotX3njuFiLqaNvnzUYDxhUvKd2
-2K1es1ggispgP+eb1bkMApxecf2rqmSUEcvsuTWip4oGZPBLGDQeNKHkCUVbj4wT
-yWDIRtto3wi+4CFPEVzw+htj1cQfTstPqUdG7NSOmLQggedoUdv7AJm4MJJiyEax
-l+IAf6Afwrrm3eOSv0PgoUxOrUb9vhIoL8ih8gtiqvQ9qYaRQfQA/w3Z0Su2Yfoc
-fQS8Uw99qG+oTgieG6F6ud8+hMZAYVZFqbU+ztzMyDE6h4Hflkt6VNJ0Hk0VoF38
-TTs77pHXXBbLD6SzR6tbNuR9r/lbmC8Qf2A1ZAThR0iuGhNRFtUPo28GxakxGdLZ
-9kHIxjl7EN/gsmYTwuEhr+yfNtLwtSH0ojeqbDmgufvgh+SITCtyNDAUspjrZYEt
-F0NHRpSom2NFVELMqMRydU/ncph1rGZgVp6/zVj6xIlhKmqj5P1y/9B0c4Tu1CzJ
-pkJ5wwARAQABiQLpBBgBCgDTSBSAAAAAABcAKHZlcmlmaWVkQHRvcnByb2plY3Qu
-b3JnREY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMk8UgAAA
-AAAeAChicmlkZ2VzQGJyaWRnZXMudG9ycHJvamVjdC5vcmdERjgxMTEwOUUxN0M4
-QkYxMzRCNUVFQjY4REM0M0EyODQ4ODIxRTMyKhpodHRwczovL2JyaWRnZXMudG9y
-cHJvamVjdC5vcmcvcG9saWN5LnR4dAIbDAUCVIoE4QUJA8NNQwAKCRCNxDooSIIe
-Mo7JEADDBtQpYxPhbj3MT0xpk96EDlon/5yHVf+cnk1pNisc+HkJsVe1nh7gAWOz
-wJKdeqOVpgxiJTxIQdl6mipKwwFi0DreP7h56s1WQkuSSWJzqssAwWHfVAsX13fV
-zWd0XyxN/OF9ZKQjX4qwpJ/na631PSwZLvHYhMaZnb9pjNwC5/PEKRmFqLbQT6Px
-12miZT6ToPDCczHxJ4BxbEGVU+PtRsHwmTRT3JhxFNDfeVd+uwsQIMidJbUoqVW7
-fe2zNd0TaWyz4Rw087oZE2OXdctjvtsu8fzXx6d/tkazI6cUOqoaMTR41KEu5X0T
-BpWSAMADBYjNs9QRWXX7ZlsJRUSCX1EKbMhgoL6KIGceIkjH61M/LF6HqDgSgSWt
-h+LIYGa+LrB/6819o32QSOSHHJ5+NJrbCSaLgKE/LKnf92V2QbZE8IGY6EOSjHqn
-n1+j+CLRKY/kUyvk+1TumTghjg/aDs/8Jv8PvgSWLQ0q1rxHYbX7q9ZJhYC/4LdR
-ya/Cho6w2l0N3tV/IMAwvFNHsaiIiiwfoOQbkBUvkyzBwjKt96Ai4I0QKt/63uH0
-drQhlJEgIyGkOrorBByVqZAQdnoLENYIu6tDUj0bTbGObKqua4iPlSK3/g40zCm4
-9OgcN7A8kFuNpgp2EHqj1/jrwd7mZYKsWTuGiR/7fwXf+4xbvg==
-=raCx
------END PGP PUBLIC KEY BLOCK-----
diff --git a/.gnupg/gpg.conf b/.gnupg/gpg.conf
deleted file mode 100644
index d4a9913..0000000
--- a/.gnupg/gpg.conf
+++ /dev/null
@@ -1,96 +0,0 @@
-##
-## Options for GnuPG
-##
-## :author: isis <isis(a)patternsinthevoid.net>
-
-no-greeting
-no-emit-version
-charset utf-8
-display-charset utf-8
-utf8-strings
-keyid-format long
-default-key 8DC43A2848821E32
-trusted-key CBD97AA24E8E472E
-
-# When outputting certificates, view user IDs distinctly from keys:
-fixed-list-mode
-
-verify-options no-show-photos show-uid-validity show-notations show-user-notations show-policy-urls show-keyserver-urls no-pka-lookups no-pka-trust-increase
-
-list-options no-show-photos show-uid-validity no-show-unusable-uids show-unusable-subkeys show-notations show-user-notations show-policy-urls show-keyserver-urls show-sig-expire show-sig-subpackets
-
-export-options no-export-attributes
-
-# Because some mailers change lines starting with "From " to ">From "
-# it is good to handle such lines in a special way when creating
-# cleartext signatures; all other PGP versions do it this way too.
-#no-escape-from-lines
-
-## Indymedia Keyservers:
-##----------------------
-keyserver hkps://2eghzlv2wwcq7u7y.onion
-keyserver hkp://2eghzlv2wwcq7u7y.onion
-keyserver hkps://keys.indymedia.org
-keyserver hkp://keys.indymedia.org
-keyserver https://keys.indymedia.org
-keyserver http://keys.indymedia.org
-keyserver https://qtt2yl5jocgrk7nu.onion
-keyserver http://qtt2yl5jocgrk7nu.onion
-keyserver-options ca-cert-file=~/scripts/certs/keys.indymedia.org
-
-## Normal keyservers:
-##--------------------
-keyserver hkp://subkeys.pgp.net
-keyserver mailto:pgp-public-keys@keys.pgp.net
-keyserver pgp.mit.edu
-
-keyserver-options verbose verbose verbose no-include-revoked no-include-disabled no-auto-key-retrieve no-honor-keyserver-url no-honor-pka-record include-subkeys no-include-attributes
-
-#keyserver-options http-proxy=socks://127.0.0.1:59050
-
-expert
-allow-freeform-uid
-cert-digest-algo SHA512
-digest-algo SHA512
-default-preference-list SHA512 SHA384 SHA256 CAMELLIA256 AES256 ZLIB ZIP Uncompressed
-personal-cipher-preferences CAMELLIA256 AES256
-personal-digest-preferences SHA512 SHA384 SHA256
-personal-compress-preferences ZLIB ZIP
-compress-level 9
-default-cert-expire 2y
-ask-cert-expire
-ask-cert-level
-default-sig-expire 1y
-no-ask-sig-expire
-
-## algorithm to protect the key in memory:
-s2k-cipher-algo AES256
-
-## use this one to mangle the passphrases:
-s2k-digest-algo SHA512
-
-## passphrase mangling mode:
-## 0=plaintest
-## 1=salt
-## 3=salt+iteration
-s2k-mode 3
-
-## how mangly should we mangle it? 1024 < mangle < 65011712
-##
-## try "python -c'import random;a=random.randint(32505856, 65011712);print a'
-s2k-count 48454407
-
-## Don't run if we can't secure mempages
-require-secmem
-
-## Check the back sig on subkey which has made a signature
-require-cross-certification
-
-## The notation on certifications we make:
-## see http://thread.gmane.org/gmane.mail.notmuch.general/3721/focus=7234
-sig-notation bridges(a)bridges.torproject.org=%g
-cert-notation bridges(a)bridges.torproject.org=%g
-cert-notation verified(a)torproject.org=%f
-set-policy-url https://bridges.torproject.org/policy.txt
-sig-keyserver-url !https://bridges.torproject.org/key.asc
-default-keyserver-url https://bridges.torproject.org/key.asc
diff --git a/.gnupg/pubring.gpg b/.gnupg/pubring.gpg
deleted file mode 100644
index 82c5477..0000000
Binary files a/.gnupg/pubring.gpg and /dev/null differ
diff --git a/.gnupg/secring.gpg b/.gnupg/secring.gpg
deleted file mode 100644
index 5e0fb5d..0000000
Binary files a/.gnupg/secring.gpg and /dev/null differ
diff --git a/.travis.requirements.txt b/.travis.requirements.txt
index 8308ce2..a74821a 100644
--- a/.travis.requirements.txt
+++ b/.travis.requirements.txt
@@ -21,7 +21,6 @@ pycryptodome==3.9.6
Twisted==20.3.0
coverage==5.0.3
coveralls==1.10.0
-gnupg==2.3.1
ipaddr==2.2.0
mechanize==0.4.5
Pillow==6.2.2
diff --git a/CHANGELOG b/CHANGELOG
index f85283b..7524344 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+ * FIXES https://bugs.torproject.org/17548
+ This patch removes PGP support. BridgeDB's signing key expired on
+ 2015-09-11. Nobody ever complained and maintaining the bits and pieces
+ necessary to sign emails isn't worth the effort, so this patch removes
+ that feature.
+
* FIXES https://bugs.torproject.org/30941
Make our email responder more usable. This patch removes the concept of
"valid" email commands and returns bridges (obfs4, for now) no matter
diff --git a/README.rst b/README.rst
index 1a338ea..858562e 100644
--- a/README.rst
+++ b/README.rst
@@ -82,7 +82,6 @@ BridgeDB requires the following OS-level dependencies:
- python-dev
- `python3-dkim <https://pypi.org/project/dkimpy/>`__ (it contains the ``dkimverify`` binary)
- build-essential
-- gnupg (preferrably, gnupg2)
- OpenSSL>=1.0.1g
- `SQLite3 <http://www.maxmind.com/app/python>`__
- `MaxMind GeoIP <https://www.maxmind.com/en/geolocation_landing>`__
@@ -111,7 +110,7 @@ BridgeDB should work with or without a Python virtualenv.
can do::
sudo apt-get install build-essential openssl python python-dev \
- python-setuptools sqlite3 gnupg2 libgeoip-dev geoip-database
+ python-setuptools sqlite3 libgeoip-dev geoip-database
- Install Pip 1.3.1 or later. Debian has this version, but if for some
@@ -254,32 +253,6 @@ To enable using a local cache of CAPTCHAs, set the following options::
-------
---------------------
-GnuPG email signing:
---------------------
-
-In your ``bridgedb.conf`` file, make sure that::
-
- EMAIL_GPG_SIGNING_ENABLED = True
-
-and edit the following option to add the full fingerprint of the GnuPG key
-that should be used to by BridgeDB to sign outgoing emails::
-
- EMAIL_GPG_PRIMARY_KEY_FINGERPRINT
-
-The key specified by ``EMAIL_GPG_PRIMARY_KEY_FINGERPRINT`` can be a master
-key, or a subkey (with or without the private portions of its corresponding
-master key), but it **must** be inside the ``secring.gpg`` and ``pubring.gpg``
-keyrings inside the directory specified in the ``bridgedb.conf`` option::
-
- EMAIL_GPG_HOMEDIR
-
-If the key has requires a passphrase for signing, you'll also need to set
-either of::
-
- EMAIL_GPG_PASSPHRASE
- EMAIL_GPG_PASSPHRASE_FILE
-
----------------------------------------------------------
Preventing already-blocked bridges from being distributed:
diff --git a/bridgedb.conf b/bridgedb.conf
index 5a8a38e..31eb3fa 100644
--- a/bridgedb.conf
+++ b/bridgedb.conf
@@ -642,51 +642,6 @@ EMAIL_N_BRIDGES_PER_ANSWER = 3
# once we have the vidalia/tor interaction fixed for everbody.
EMAIL_INCLUDE_FINGERPRINTS = True
-#
-# Configuration options for OpenPGP signing and encryption
-# ------------------------------------------------------------------------------
-
-# Should we sign all email responses to clients with the key specified by
-# EMAIL_GPG_PRIMARY_KEY_FINGERPRINT (or one of its subkeys)?
-EMAIL_GPG_SIGNING_ENABLED = True
-
-# The directory, relative to BridgeDB's runtime directory, in which to store
-# OpenPGP keyrings and associated files.
-EMAIL_GPG_HOMEDIR = '.gnupg'
-
-# This should be a 40-character hexadecimal string containing the OpenPGP
-# fingerprint (without spaces) of the default primary key to use. The key
-# should be capable of both signing and encryption, or have subkeys capable of
-# such.
-#
-# The default primary key fingerprint below is the test key contained in the
-# '.gnupg/TESTING.subkeys.sec' and '.gnupg/TESTING.pub' files:
-EMAIL_GPG_PRIMARY_KEY_FINGERPRINT = '0017098C5DF4197E3C884DCFF1B240D43F148C21'
-
-# If the key referred to by EMAIL_GPG_PRIMARY_KEY_FINGERPRINT requires a
-# passphrase for signing or encryption, then the passphrase may be given in
-# the EMAIL_GPG_PASSPHRASE option (as a string), or it may be contained within
-# the file pointed to by EMAIL_GPG_PASSPHRASE_FILE. Currently, only one
-# passphrase is supported, so if the key specified by
-# EMAIL_GPG_PRIMARY_KEY_FINGERPRINT has multiple subkeys, those subkeys MUST
-# all have the same passphrase.
-#
-# If EMAIL_GPG_PASSPHRASE_FILE is used, and the filepath is not absolute, the
-# path is interpreted as being relative to BridgeDB's runtime directory.
-# (Note: be sure not to put any newlines after the phassphrase in the
-# EMAIL_GPG_PASSPHRASE_FILE, or else they will be interpreted as part of the
-# passphrase.)
-#
-# There are currently no safety checks on the permissions of either this
-# configuration file or the EMAIL_GPG_PASSPHRASE_FILE, so beware and use at
-# your own risk.
-#
-# If both EMAIL_GPG_PASSPHRASE and EMAIL_GPG_PASSPHRASE_FILE are ``None``,
-# then it is assumed that the key specified by
-# EMAIL_GPG_PRIMARY_KEY_FINGERPRINT does not require a passphrase.
-EMAIL_GPG_PASSPHRASE = None
-EMAIL_GPG_PASSPHRASE_FILE = None
-
#-------------------------------
# Hashring Allocation Options \
#------------------------------------------------------------------------------
diff --git a/bridgedb/configure.py b/bridgedb/configure.py
index e069ea3..ab8e08a 100644
--- a/bridgedb/configure.py
+++ b/bridgedb/configure.py
@@ -113,8 +113,7 @@ def loadConfig(configFile=None, configCls=None):
"MOAT_CERT_FILE", "MOAT_KEY_FILE",
"LOG_FILE", "COUNTRY_BLOCK_FILE",
"GIMP_CAPTCHA_DIR", "GIMP_CAPTCHA_HMAC_KEYFILE",
- "GIMP_CAPTCHA_RSA_KEYFILE", "EMAIL_GPG_HOMEDIR",
- "EMAIL_GPG_PASSPHRASE_FILE", "NO_DISTRIBUTION_FILE"]:
+ "GIMP_CAPTCHA_RSA_KEYFILE", "NO_DISTRIBUTION_FILE"]:
setting = getattr(config, attr, None)
if setting is None:
setattr(config, attr, setting)
diff --git a/bridgedb/crypto.py b/bridgedb/crypto.py
index db3d083..9bdf729 100644
--- a/bridgedb/crypto.py
+++ b/bridgedb/crypto.py
@@ -9,9 +9,9 @@
# :license: 3-clause BSD, see included LICENSE for information
"""This module contains general utilities for working with external
-cryptographic tools and libraries, including OpenSSL and GnuPG. It also
-includes utilities for creating callable HMAC functions, generating HMACs for
-data, and generating and/or storing key material.
+cryptographic tools and libraries, like OpenSSL. It also includes utilities for
+creating callable HMAC functions, generating HMACs for data, and generating
+and/or storing key material.
.. py:module:: bridgedb.crypto
:synopsis: BridgeDB general cryptographic utilities.
@@ -19,12 +19,10 @@ data, and generating and/or storing key material.
::
bridgedb.crypto
- |_getGPGContext() - Get a pre-configured GPGME context.
|_getHMAC() - Compute an HMAC with some key for some data.
|_getHMACFunc() - Get a callable for producing HMACs with the given key.
|_getKey() - Load the master HMAC key from a file, or create a new one.
|_getRSAKey() - Load an RSA key from a file, or create a new one.
- |_gpgSignMessage() - Sign a message string according to a GPGME context.
|_writeKeyToFile() - Write to a file readable only by the process owner.
|
\_SSLVerifyingContextFactory - OpenSSL.SSL.Context factory which verifies
@@ -40,7 +38,6 @@ data, and generating and/or storing key material.
from __future__ import absolute_import
from __future__ import unicode_literals
-import gnupg
import hashlib
import hmac
import io
@@ -264,96 +261,6 @@ def removePKCS1Padding(message):
return unpadded
-def initializeGnuPG(config):
- """Initialize a GnuPG interface and test our configured keys.
-
- .. note:: This function uses python-gnupg_.
-
- :type config: :class:`bridgedb.persistent.Conf`
- :param config: The loaded config file.
- :rtype: 2-tuple
- :returns: If ``EMAIL_GPG_SIGNING_ENABLED`` isn't ``True``, or we couldn't
- initialize GnuPG and make a successful test signature with the
- specified key, then a 2-tuple of ``None`` is returned. Otherwise, the
- first item in the tuple is a :class:`gnupg.GPG` interface_ with the
- GnuPG homedir set to the ``EMAIL_GPG_HOMEDIR`` option and the signing
- key specified by the ``EMAIL_GPG_SIGNING_KEY_FINGERPRINT`` option in
- bridgedb.conf set as the default key. The second item in the tuple is
- a signing function with the passphrase (as specified in either
- ``EMAIL_GPG_PASSPHRASE`` or ``EMAIL_GPG_PASSPHRASE_FILE``) already
- set.
-
- .. _python-gnupg: https://pypi.python.org/pypi/gnupg/
- .. _interface: https://python-gnupg.readthedocs.org/en/latest/gnupg.html#gnupg-module
- """
- ret = (None, None)
-
- if not config.EMAIL_GPG_SIGNING_ENABLED:
- return ret
-
- homedir = config.EMAIL_GPG_HOMEDIR
- primary = config.EMAIL_GPG_PRIMARY_KEY_FINGERPRINT
- passphrase = config.EMAIL_GPG_PASSPHRASE
- passFile = config.EMAIL_GPG_PASSPHRASE_FILE
-
- logging.info("Using %s as our GnuPG home directory..." % homedir)
- gpg = gnupg.GPG(homedir=homedir)
- logging.info("Initialized GnuPG interface using %s binary with version %s."
- % (gpg.binary, gpg.binary_version))
-
- primarySK = None
- primaryPK = None
- secrets = gpg.list_keys(secret=True)
- publics = gpg.list_keys()
-
- if not secrets:
- logging.warn("No secret keys found in %s!" % gpg.secring)
- return ret
-
- primarySK = list(filter(lambda key: key['fingerprint'] == primary, secrets))
- primaryPK = list(filter(lambda key: key['fingerprint'] == primary, publics))
-
- if primarySK and primaryPK:
- logging.info("Found GnuPG primary key with fingerprint: %s" % primary)
-
- for sub in primaryPK[0]['subkeys']:
- logging.info(" Subkey: %s Usage: %s" % (sub[0], sub[1].upper()))
- else:
- logging.warn("GnuPG key %s could not be found in %s!" % (primary, gpg.secring))
- return ret
-
- if passphrase:
- logging.info("Read GnuPG passphrase from config.")
- elif passFile:
- try:
- with open(passFile) as fh:
- passphrase = fh.read()
- except (IOError, OSError):
- logging.error("Could not open GnuPG passphrase file: %s!" % passFile)
- else:
- logging.info("Read GnuPG passphrase from file: %s" % passFile)
-
- def gpgSignMessage(message):
- """Sign **message** with the default key specified by
- ``EMAIL_GPG_PRIMARY_KEY_FINGERPRINT``.
-
- :param str message: A message to sign.
- :rtype: str or ``None``.
- :returns: A string containing the clearsigned message, or ``None`` if
- the signing failed.
- """
- sig = gpg.sign(message, default_key=primary, passphrase=passphrase)
- if sig and sig.data:
- return sig.data
-
- logging.debug("Testing signature created with GnuPG key...")
- sig = gpgSignMessage("Testing 1 2 3")
- if sig:
- logging.info("Test signature with GnuPG key %s okay:\n%s" % (primary, sig))
- return (gpg, gpgSignMessage)
-
- return ret
-
class SSLVerifyingContextFactory(ssl.CertificateOptions):
"""``OpenSSL.SSL.Context`` factory which does full certificate-chain and
diff --git a/bridgedb/distributors/email/autoresponder.py b/bridgedb/distributors/email/autoresponder.py
index 5e1fcd0..9b0ac53 100644
--- a/bridgedb/distributors/email/autoresponder.py
+++ b/bridgedb/distributors/email/autoresponder.py
@@ -55,7 +55,6 @@ from bridgedb import safelog
from bridgedb.distributors.email import dkim
from bridgedb.distributors.email import request
from bridgedb.distributors.email import templates
-from bridgedb.distributors.email.distributor import EmailRequestedKey
from bridgedb.distributors.email.distributor import TooSoonEmail
from bridgedb.distributors.email.distributor import IgnoreEmail
from bridgedb.parse import addr
@@ -100,9 +99,6 @@ def createResponseBody(lines, context, client, lang='en'):
# Otherwise they must have requested bridges:
interval = context.schedule.intervalStart(time.time())
bridges = context.distributor.getBridges(bridgeRequest, interval)
- except EmailRequestedKey as error:
- logging.info(error)
- return templates.buildKeyMessage(translator, client)
except TooSoonEmail as error:
logging.info("Got a mail too frequently: %s." % error)
return templates.buildSpamWarning(translator, client)
@@ -120,7 +116,7 @@ def createResponseBody(lines, context, client, lang='en'):
return templates.buildAnswerMessage(translator, client, answer)
def generateResponse(fromAddress, client, body, subject=None,
- messageID=None, gpgSignFunc=None):
+ messageID=None):
"""Create an :class:`EmailResponse`, which acts like an
:class:`io.StringIO` instance, by creating and writing all headers and the
email body into the file-like :attr:`EmailResponse.mailfile`.
@@ -131,21 +127,15 @@ def generateResponse(fromAddress, client, body, subject=None,
:param client: The client's email address which should be in the
``'To:'`` header of the response email.
:param str subject: The string to write to the ``'Subject:'`` header.
- :param str body: The body of the email. If a **gpgSignFunc** is also
- given, then :meth:`EmailResponse.writeBody` will generate and include
- an ascii-armored OpenPGP signature in the **body**.
+ :param str body: The body of the email.
:type messageID: ``None`` or :any:`str`
:param messageID: The :rfc:`2822` specifier for the ``'Message-ID:'``
header, if including one is desirable.
- :type gpgSignFunc: callable
- :param gpgSignFunc: If given, this should be a callable function for
- signing messages. See :func:`bridgedb.crypto.initializeGnuPG` for
- obtaining a pre-configured **gpgSignFunc**.
:returns: An :class:`EmailResponse` which contains the entire email. To
obtain the contents of the email, including all headers, simply use
:meth:`EmailResponse.readContents`.
"""
- response = EmailResponse(gpgSignFunc)
+ response = EmailResponse()
response.to = client
response.writeHeaders(fromAddress.encode('utf-8'), str(client), subject,
inReplyTo=messageID)
@@ -168,10 +158,7 @@ class EmailResponse(object):
.. todo:: At some point, we may want to change this class to optionally
handle creating Multipart MIME encoding messages, so that we can
- include attachments. (This would be useful for attaching our GnuPG
- keyfile, for example, rather than simply pasting it into the body of
- the email.)
-
+ include attachments.
:var str delimiter: Delimiter between lines written to the
:data:`mailfile`.
@@ -180,18 +167,12 @@ class EmailResponse(object):
:var to: The client's email address, to which this response should be sent.
"""
- def __init__(self, gpgSignFunc=None):
+ def __init__(self):
"""Create a response to an email we have recieved.
This class deals with correctly formatting text for the response email
headers and the response body into an instance of :data:`mailfile`.
-
- :type gpgSignFunc: callable
- :param gpgSignFunc: If given, this should be a callable function for
- signing messages. See :func:`bridgedb.crypto.initializeGnuPG` for
- obtaining a pre-configured **gpgSignFunc**.
"""
- self.gpgSign = gpgSignFunc
self.mailfile = io.StringIO()
self.delimiter = '\n'
self.closed = False
@@ -338,18 +319,9 @@ class EmailResponse(object):
def writeBody(self, body):
"""Write the response body into the :attr:`mailfile`.
- If :attr:`EmailResponse.gpgSignFunc` is set, and signing is configured,
- the **body** will be automatically signed before writing its contents
- into the :attr:`mailfile`.
-
:param str body: The body of the response email.
"""
logging.info("Writing email body...")
- if self.gpgSign:
- logging.info("Attempting to sign email...")
- sig = self.gpgSign(body)
- if sig:
- body = sig
self.writelines(body)
@@ -433,8 +405,7 @@ class SMTPAutoresponder(smtp.SMTPClient):
messageID = self.incoming.message.get("Message-ID", None)
subject = self.incoming.message.get("Subject", None)
response = generateResponse(recipient, client,
- body, subject, messageID,
- self.incoming.context.gpgSignFunc)
+ body, subject, messageID)
return response
def getMailTo(self):
diff --git a/bridgedb/distributors/email/distributor.py b/bridgedb/distributors/email/distributor.py
index c6ac2fd..77bcdb9 100644
--- a/bridgedb/distributors/email/distributor.py
+++ b/bridgedb/distributors/email/distributor.py
@@ -20,7 +20,7 @@ bridgedb.distributors.email.autoresponder
A :class:`~bridgedb.distribute.Distributor` which hands out :class:`bridges
<bridgedb.bridges.Bridge>` to clients via an email interface.
-.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailRequestedKey EmailDistributor
+.. inheritance-diagram:: IgnoreEmail TooSoonEmail EmailDistributor
:parts: 1
"""
@@ -55,10 +55,6 @@ class TooSoonEmail(addr.BadEmail):
"""Raised when we got a request from this address too recently."""
-class EmailRequestedKey(Exception):
- """Raised when an incoming email requested a copy of our GnuPG keys."""
-
-
class EmailDistributor(Distributor):
"""Object that hands out bridges based on the email address of an incoming
request and the current time period.
diff --git a/bridgedb/distributors/email/request.py b/bridgedb/distributors/email/request.py
index 90576c1..6484fe3 100644
--- a/bridgedb/distributors/email/request.py
+++ b/bridgedb/distributors/email/request.py
@@ -45,7 +45,6 @@ import re
from bridgedb import strings
from bridgedb import bridgerequest
-from bridgedb.distributors.email.distributor import EmailRequestedKey
#: A regular expression for matching the Pluggable Transport method TYPE in
@@ -62,7 +61,6 @@ UNBLOCKED_PATTERN = re.compile(UNBLOCKED_REGEXP)
#: valid as long as it wasn't quoted, i.e., the line didn't start with a '>'
#: character.
GET_LINE = re.compile("([^>].*)?get")
-KEY_LINE = re.compile("([^>].*)?key")
IPV6_LINE = re.compile("([^>].*)?ipv6")
TRANSPORT_LINE = re.compile("([^>].*)?transport")
UNBLOCKED_LINE = re.compile("([^>].*)?unblocked")
@@ -75,7 +73,6 @@ def determineBridgeRequestOptions(lines):
and/or ``CC`` will *always* be stored as a *lowercase* string.
:param list lines: A list of lines from an email, including the headers.
- :raises EmailRequestedKey: if the client requested our GnuPG key.
:rtype: :class:`EmailBridgeRequest`
:returns: A :class:`~bridgerequest.BridgeRequest` with all of the requested
parameters set. The returned ``BridgeRequest`` will have already had
@@ -93,9 +90,6 @@ def determineBridgeRequestOptions(lines):
if GET_LINE.match(line) is not None:
request.isValid(True)
logging.debug("Email request was valid.")
- if KEY_LINE.match(line) is not None:
- request.wantsKey(True)
- raise EmailRequestedKey("Email requested a copy of our GnuPG key.")
if IPV6_LINE.match(line) is not None:
request.withIPv6()
if TRANSPORT_LINE.match(line) is not None:
@@ -127,22 +121,6 @@ class EmailBridgeRequest(bridgerequest.BridgeRequestBase):
:class:`~bridgedb.distributors.email.distributor.EmailDistributor`.
"""
super(EmailBridgeRequest, self).__init__()
- self._wantsKey = False
-
- def wantsKey(self, wantsKey=None):
- """Get or set whether this bridge request wanted our GnuPG key.
-
- If called without parameters, this method will return the current
- state, otherwise (if called with the **wantsKey** parameter set), it
- will set the current state for whether or not this request wanted our
- key.
-
- :param bool wantsKey: If given, set the validity state of this
- request. Otherwise, get the current state.
- """
- if wantsKey is not None:
- self._wantsKey = bool(wantsKey)
- return self._wantsKey
def withoutBlockInCountry(self, line):
"""This request was for bridges not blocked in **country**.
diff --git a/bridgedb/distributors/email/server.py b/bridgedb/distributors/email/server.py
index 063b640..f18a5ad 100644
--- a/bridgedb/distributors/email/server.py
+++ b/bridgedb/distributors/email/server.py
@@ -66,7 +66,6 @@ from zope.interface import implementer
from bridgedb import __version__
from bridgedb import safelog
-from bridgedb.crypto import initializeGnuPG
from bridgedb.distributors.email import autoresponder
from bridgedb.distributors.email import templates
from bridgedb.distributors.email import request
@@ -97,13 +96,6 @@ class MailServerContext(object):
:ivar int fuzzyMatch: An integer specifying the maximum Levenshtein
Distance from an incoming email address to a blacklisted email address
for the incoming email to be dropped.
- :ivar gpg: A :class:`gnupg.GPG` interface_, as returned by
- :func:`~bridgedb.crypto.initialiseGnuPG`, or ``None`` if we couldn't
- initialize GnuPG for some reason.
- :ivar gpgSignFunc: A callable which signs a message, e.g. the one returned
- from :func:`~bridgedb.crypto.initialiseGnuPG`.
-
- .. _interface: https://pythonhosted.org/gnupg/gnupg.html#gnupg-module
"""
def __init__(self, config, distributor, schedule):
@@ -139,8 +131,6 @@ class MailServerContext(object):
self.blacklist = config.EMAIL_BLACKLIST or []
self.fuzzyMatch = config.EMAIL_FUZZY_MATCH or 0
- self.gpg, self.gpgSignFunc = initializeGnuPG(config)
-
def buildCanonicalDomainMap(self):
"""Build a map for all email provider domains from which we will accept
emails to their canonical domain name.
diff --git a/bridgedb/distributors/email/templates.py b/bridgedb/distributors/email/templates.py
index 2eb0a31..44450ea 100644
--- a/bridgedb/distributors/email/templates.py
+++ b/bridgedb/distributors/email/templates.py
@@ -67,9 +67,6 @@ def addGreeting(template):
return greeting
-def addKeyfile(template):
- return u'%s\n\n' % strings.BRIDGEDB_OPENPGP_KEY
-
def addBridgeAnswer(template, answer):
# Give the user their bridges, i.e. the `answer`:
bridgeLines = u""
@@ -88,10 +85,6 @@ def addHowto(template):
"""
return template.gettext(strings.HOWTO_TBB[2])
-def buildKeyMessage(template, clientAddress=None):
- message = addKeyfile(template)
- return message
-
def buildAnswerMessage(template, clientAddress=None, answer=None):
try:
message = addGreeting(template)
diff --git a/bridgedb/distributors/https/server.py b/bridgedb/distributors/https/server.py
index be99262..b2de4b1 100644
--- a/bridgedb/distributors/https/server.py
+++ b/bridgedb/distributors/https/server.py
@@ -1143,7 +1143,6 @@ def addWebServer(config, distributor):
info = InfoResource()
robots = static.File(os.path.join(TEMPLATE_DIR, 'robots.txt'))
assets = static.File(os.path.join(TEMPLATE_DIR, 'assets/'))
- keys = static.Data(strings.BRIDGEDB_OPENPGP_KEY.encode('utf-8'), 'text/plain')
csp = CSPResource(enabled=config.CSP_ENABLED,
includeSelf=config.CSP_INCLUDE_SELF,
reportViolations=config.CSP_REPORT_ONLY,
@@ -1152,7 +1151,6 @@ def addWebServer(config, distributor):
root = CustomErrorHandlingResource()
root.putChild(b'', index)
root.putChild(b'robots.txt', robots)
- root.putChild(b'keys', keys)
root.putChild(b'assets', assets)
root.putChild(b'options', options)
root.putChild(b'howto', howto)
diff --git a/bridgedb/distributors/https/templates/base.html b/bridgedb/distributors/https/templates/base.html
index b42d252..2f502a9 100644
--- a/bridgedb/distributors/https/templates/base.html
+++ b/bridgedb/distributors/https/templates/base.html
@@ -98,8 +98,6 @@ ${next.body(strings, langs, rtl=rtl, lang=lang, langOverride=langOverride, **kwa
·
<a href="https://gitweb.torproject.org/bridgedb.git/tree/CHANGELOG">
<i class="icon icon-large icon-rocket"><span id="footer-changelog"> ${_("Changelog")}</span></i></a>
- ·
- <a href="../keys"><i class="icon icon-large icon-key"><span id="footer-keys"> ${_("Public Keys")}</span></i></a>
</p>
<br />
<p>© The Tor Project</p>
diff --git a/bridgedb/i18n/templates/bridgedb.pot b/bridgedb/i18n/templates/bridgedb.pot
index 85958bd..bb78824 100644
--- a/bridgedb/i18n/templates/bridgedb.pot
+++ b/bridgedb/i18n/templates/bridgedb.pot
@@ -5,11 +5,11 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: bridgedb 0.10.0+7.gbca6496.dirty\n"
+"Project-Id-Version: bridgedb 0.10.0+10.g96de503\n"
"Report-Msgid-Bugs-To: "
"'https://trac.torproject.org/projects/tor/newticket?component=BridgeDB&keywo…"
"=bridgedb-reported,msgid&cc=isis,sysrqb&owner=isis'\n"
-"POT-Creation-Date: 2020-04-07 10:14-0700\n"
+"POT-Creation-Date: 2020-04-09 14:45-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL(a)li.org>\n"
@@ -66,10 +66,6 @@ msgstr ""
msgid "Changelog"
msgstr ""
-#: bridgedb/distributors/https/templates/base.html:102
-msgid "Public Keys"
-msgstr ""
-
#: bridgedb/distributors/https/templates/bridges.html:35
msgid "Select All"
msgstr ""
@@ -180,15 +176,15 @@ msgstr ""
msgid "%sG%set Bridges"
msgstr ""
-#: bridgedb/strings.py:42
+#: bridgedb/strings.py:33
msgid "[This is an automated email.]"
msgstr ""
-#: bridgedb/strings.py:44
+#: bridgedb/strings.py:35
msgid "Here are your bridges:"
msgstr ""
-#: bridgedb/strings.py:46
+#: bridgedb/strings.py:37
#, python-format
msgid ""
"You have exceeded the rate limit. Please slow down! The minimum time between\n"
@@ -196,7 +192,7 @@ msgid ""
"ignored."
msgstr ""
-#: bridgedb/strings.py:49
+#: bridgedb/strings.py:40
msgid ""
"If these bridges are not what you need, reply to this email with one of\n"
"the following commands in the message body:"
@@ -206,7 +202,7 @@ msgstr ""
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
#. TRANSLATORS: Please DO NOT translate "Tor".
#. TRANSLATORS: Please DO NOT translate "Tor Network".
-#: bridgedb/strings.py:59
+#: bridgedb/strings.py:50
#, python-format
msgid ""
"BridgeDB can provide bridges with several %stypes of Pluggable Transports%s,\n"
@@ -218,7 +214,7 @@ msgid ""
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Pluggable Transports".
-#: bridgedb/strings.py:66
+#: bridgedb/strings.py:57
msgid ""
"Some bridges with IPv6 addresses are also available, though some Pluggable\n"
"Transports aren't IPv6 compatible.\n"
@@ -230,7 +226,7 @@ msgstr ""
#. regular, or unexciting". Like vanilla ice cream. It refers to bridges
#. which do not have Pluggable Transports, and only speak the regular,
#. boring Tor protocol. Translate it as you see fit. Have fun with it.
-#: bridgedb/strings.py:75
+#: bridgedb/strings.py:66
#, python-format
msgid ""
"Additionally, BridgeDB has plenty of plain-ol'-vanilla bridges %s without any"
@@ -241,21 +237,21 @@ msgid ""
"\n"
msgstr ""
-#: bridgedb/strings.py:87 bridgedb/test/test_https.py:356
+#: bridgedb/strings.py:78 bridgedb/test/test_https.py:356
msgid "What are bridges?"
msgstr ""
-#: bridgedb/strings.py:88
+#: bridgedb/strings.py:79
#, python-format
msgid "%s Bridges %s are Tor relays that help you circumvent censorship."
msgstr ""
-#: bridgedb/strings.py:93
+#: bridgedb/strings.py:84
msgid "I need an alternative way of getting bridges!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "get transport obfs4".
-#: bridgedb/strings.py:95
+#: bridgedb/strings.py:86
#, python-format
msgid ""
"Another way to get bridges is to send an email to %s. Leave the email subject"
@@ -267,32 +263,32 @@ msgid ""
"providers: %s or %s."
msgstr ""
-#: bridgedb/strings.py:103
+#: bridgedb/strings.py:94
msgid "My bridges don't work! I need help!"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
#. TRANSLATORS: The two '%s' are substituted with "Tor Browser Manual" and
#. "Support Portal", respectively.
-#: bridgedb/strings.py:107
+#: bridgedb/strings.py:98
#, python-format
msgid "If your Tor Browser cannot connect, please take a look at the %s and our %s."
msgstr ""
-#: bridgedb/strings.py:111
+#: bridgedb/strings.py:102
msgid "Here are your bridge lines:"
msgstr ""
-#: bridgedb/strings.py:112
+#: bridgedb/strings.py:103
msgid "Get Bridges!"
msgstr ""
-#: bridgedb/strings.py:116
+#: bridgedb/strings.py:107
msgid "Bridge distribution mechanisms"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "BridgeDB", "HTTPS", and "Moat".
-#: bridgedb/strings.py:118
+#: bridgedb/strings.py:109
#, python-format
msgid ""
"BridgeDB implements four mechanisms to distribute bridges: \"HTTPS\", "
@@ -306,7 +302,7 @@ msgid ""
"mechanisms is."
msgstr ""
-#: bridgedb/strings.py:124
+#: bridgedb/strings.py:115
#, python-format
msgid ""
"The \"HTTPS\" distribution mechanism hands out bridges over this website. To"
@@ -316,7 +312,7 @@ msgid ""
"solve the subsequent CAPTCHA."
msgstr ""
-#: bridgedb/strings.py:128
+#: bridgedb/strings.py:119
#, python-format
msgid ""
"The \"Moat\" distribution mechanism is part of Tor Browser, allowing users to"
@@ -329,7 +325,7 @@ msgid ""
"bridges."
msgstr ""
-#: bridgedb/strings.py:134
+#: bridgedb/strings.py:125
#, python-format
msgid ""
"Users can request bridges from the \"Email\" distribution mechanism by "
@@ -339,11 +335,11 @@ msgid ""
"email body."
msgstr ""
-#: bridgedb/strings.py:138
+#: bridgedb/strings.py:129
msgid "Reserved"
msgstr ""
-#: bridgedb/strings.py:139
+#: bridgedb/strings.py:130
#, python-format
msgid ""
"BridgeDB maintains a small number of bridges that are not distributed\n"
@@ -357,11 +353,11 @@ msgid ""
"called \"Unallocated\" in %sbridge pool assignment%s files."
msgstr ""
-#: bridgedb/strings.py:146
+#: bridgedb/strings.py:137
msgid "None"
msgstr ""
-#: bridgedb/strings.py:147
+#: bridgedb/strings.py:138
msgid ""
"Bridges whose distribution mechanism is \"None\" are not distributed by "
"BridgeDB.\n"
@@ -372,33 +368,33 @@ msgid ""
"it will then change to the bridge's actual distribution mechanism.\n"
msgstr ""
-#: bridgedb/strings.py:157
+#: bridgedb/strings.py:148
msgid "Please select options for bridge type:"
msgstr ""
-#: bridgedb/strings.py:158
+#: bridgedb/strings.py:149
msgid "Do you need IPv6 addresses?"
msgstr ""
-#: bridgedb/strings.py:159
+#: bridgedb/strings.py:150
#, python-format
msgid "Do you need a %s?"
msgstr ""
-#: bridgedb/strings.py:163
+#: bridgedb/strings.py:154
msgid "Your browser is not displaying images properly."
msgstr ""
-#: bridgedb/strings.py:164
+#: bridgedb/strings.py:155
msgid "Enter the characters from the image above..."
msgstr ""
-#: bridgedb/strings.py:168
+#: bridgedb/strings.py:159
msgid "How to start using your bridges"
msgstr ""
#. TRANSLATORS: Please DO NOT translate "Tor Browser".
-#: bridgedb/strings.py:170
+#: bridgedb/strings.py:161
#, python-format
msgid ""
" First, you need to %sdownload Tor Browser%s. Our Tor Browser User\n"
@@ -407,28 +403,22 @@ msgid ""
" are using Android, %sclick here%s."
msgstr ""
-#: bridgedb/strings.py:175
+#: bridgedb/strings.py:166
msgid ""
"Add these bridges to your Tor Browser by opening your browser\n"
"preferences, clicking on \"Tor\", and then adding them to the \"Provide a\n"
"bridge\" field."
msgstr ""
-#: bridgedb/strings.py:182
+#: bridgedb/strings.py:173
msgid "(Request unobfuscated Tor bridges.)"
msgstr ""
-#: bridgedb/strings.py:183
+#: bridgedb/strings.py:174
msgid "(Request IPv6 bridges.)"
msgstr ""
-#: bridgedb/strings.py:184
+#: bridgedb/strings.py:175
msgid "(Request obfs4 obfuscated bridges.)"
msgstr ""
-#. TRANSLATORS: Please DO NOT translate "BridgeDB".
-#. TRANSLATORS: Please DO NOT translate "GnuPG".
-#: bridgedb/strings.py:187
-msgid "(Get a copy of BridgeDB's public GnuPG key.)"
-msgstr ""
-
diff --git a/bridgedb/strings.py b/bridgedb/strings.py
index 6bccf81..2a1e60d 100644
--- a/bridgedb/strings.py
+++ b/bridgedb/strings.py
@@ -8,16 +8,7 @@
# (c) 2007-2017, all entities within the AUTHORS file
# :license: 3-clause BSD, see included LICENSE for information
-"""Commonly used string constants.
-
-.. todo:: The instructions for the OpenPGP keys in
- :data:`BRIDGEDB_OPENPGP_KEY` are not translated… should we translate them?
- Should we tell users where to obtain GPG4Win/GPGTools/gnupg? Should those
- instruction be that verbose? Or should we get rid of the instructions
- altogether, and assume that any encouragement towards using GPG will just
- make users more frustrated, and (possibly) (mis-)direct that frustration
- at Tor or BridgeDB?
-"""
+"""Commonly used string constants."""
from __future__ import unicode_literals
@@ -183,8 +174,6 @@ EMAIL_COMMANDS = {
"get ipv6": _("(Request IPv6 bridges.)"),
"get transport obfs4": _("(Request obfs4 obfuscated bridges.)"),
# TRANSLATORS: Please DO NOT translate "BridgeDB".
- # TRANSLATORS: Please DO NOT translate "GnuPG".
- "get key": _("(Get a copy of BridgeDB's public GnuPG key.)"),
}
#-----------------------------------------------------------------------------
@@ -318,258 +307,3 @@ EMAIL_REFERENCE_LINKS = {
"HOWTO_TBB2": "[1]: https://tb-manual.torproject.org/bridges/#entering-bridge-addresses",
"HOWTO_TBB3": "[2]: https://tb-manual.torproject.org/mobile-tor/#circumvention",
}
-
-BRIDGEDB_OPENPGP_KEY = """\
-# 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: 2015-09-11]
-# Key fingerprint = DF81 1109 E17C 8BF1 34B5 EEB6 8DC4 3A28 4882 1E32
-# uid BridgeDB <bridges(a)bridges.torproject.org>
-# sub 4096R/21B554E95938F4D0 2013-09-11 [expires: 2015-09-11]
-# Key fingerprint = 9FE3 9D1A 7438 9223 3B3F 66F2 21B5 54E9 5938 F4D0
-# sub 4096R/E7793047C5B54232 2013-09-11 [expires: 2015-09-11]
-# Key fingerprint = CFFB 8469 9048 37E7 8CAE 322C E779 3047 C5B5 4232
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQINBFIv8YABEADRqvfLB4xWj3Fz+HEmUUt/qbJnZhqIjo5WBHaBJOmrzx1c9fLN
-aYG36Hgo6A7NygI1oQmFnDinSrZAtrPaT63d1Jg49yZwr/OhMaxHYJElMFHGJ876
-kLZHmQTysquYKDHhv+fH51t7UVaZ9NkP5cI+V3pqck0DW5DwMsVJXNaU317kk9me
-mPJUDMb5FM4d2Vtk1N+54bHJgpgmnukNtpJmRyHRbZBqNMln5nWF7vdZ4u5PGPWj
-bA0rPZhayeE3FQ0MHiGL12kHAy30pfg54QfPJDQBCywjABetRE+xaM9TcS+R31Pf
-2VbLeb+Km7QpHMwOXI5xZLss9BAWm9EBbmXxuqaRBHyi830jjCrK9UYuzzOqKoUV
-Mk1BRelZTFnGPWeVTE+Ps+pwJ0Dwx4ghppJBCoArmEbkNliblxR/2wYOOFi/ZVA4
-Zc2ok9T3rBLVg07b7ezFUScGiTnc7ac7hp6r8Qsh09ZbhRr9erK/n194aEvkXTfr
-qepwrAE7YeF4YuR206UOFFWDhxWDLbRu0gIWgrevEQu/cvQPrO9uH5fL6Gw/+mNP
-Q/NIteejhkDyvyTUKyBu7x+Gls71zT2u/X13eOAJ8IxBkSVRKQ8tRD+oqJkWplOf
-+BpaGU+g6u4kT2AzFDxTOupfrYcPvORTAV/V3suys2YQE4x422GASXDivQARAQAB
-tClCcmlkZ2VEQiA8YnJpZGdlc0BicmlkZ2VzLnRvcnByb2plY3Qub3JnPokDJQQT
-AQoBD0gUgAAAAAAXACh2ZXJpZmllZEB0b3Jwcm9qZWN0Lm9yZ0RGODExMTA5RTE3
-QzhCRjEzNEI1RUVCNjhEQzQzQTI4NDg4MjFFMzJPFIAAAAAAHgAoYnJpZGdlc0Bi
-cmlkZ2VzLnRvcnByb2plY3Qub3JnREY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERD
-NDNBMjg0ODgyMUUzMioaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2plY3Qub3JnL3Bv
-bGljeS50eHQCGwEDCw0JBBUKCQgEFgIBAAIeAQIXgCcYaHR0cHM6Ly9icmlkZ2Vz
-LnRvcnByb2plY3Qub3JnL2tleS5hc2MFAlSKBKIFCQPDTiIACgkQjcQ6KEiCHjIs
-jg//bJ12eRnBMfIGzOGh+T4wz7/YyKLfARAMnqDnSxhTxuE+M5hWm3QbxP03R6eY
-x+PKwQaDJSmm7HhRhltb7QXUe8dqjnocFwwagpoLZ/81mBLxByqg5TKHGGIGy+DX
-omIzCq5ijx1IUkHlgh708a5alG7bjRTqedT4Wxxyl6psGzDhGQdS8bqx/f32nQaE
-h41l+A/EY1g2HVqky63ZHAP3S2v+mWCrk5DnkElc0229MXqaBuEr4nbYMXRkahMb
-E2gnCmdSoeD21AY6bNyz7IcJGpyKCx9+hVgPjpm3J23JEYyPL+s48jn6QcI/Q2gD
-yAtgU65y6IrdYn8SwkABI1FIq9WAwG7DaInxvkqkYqyBQLaZJEMyX8NTBvFoT5JS
-jnkxG0xu61Vxq0BLYBIOJE0VFHAJ40/jOvSxQJkQhu9G4BK7htnADbtstmMDMM3q
-xuuO5pcj2rl7YthNunyZ1yhPHXijUUyKrwR9piENpptztFBVN6+ijqU/TmWMOtbH
-X7p9F+3tXCHHqwO5U/JMtsb/9M39MR8BrdcLc7m6dCpeuSUuR2LLroh+MoMJGviI
-iesxHF95kFqkJAecW1Z3eKL9vrlbfO3waeuCi18k1TePnZuG5lmf2KjKDW5vHK4O
-WFqvvfK2kxkCUjvGdLeTOAVOV+X+PQ23jvBJO2bS7YbOb9C5Ag0EUi/ygQEQALZ/
-p7xRINHY7MMf3/bo/I0WRxWHd1AE9tRToyEg1S2u1YrWWL5M9D8saRsp9cpnpGEu
-hW3vu7G4nasY27qOz4bSKu1YMAVIC58v1tEnBqdo1zErNjhs38PrmJKbbs9tDfYY
-Oi2x0GlhMbIrNStcZpnCdLa6U6NLMbggDL1GxjMPYBMi4TtLgcIeRDUSjsZscZkg
-Kxs5QkSVc3SrYyraayIc8WtIpDLcxPt6/g90rbatZzBfO+93Rz7qUXHmgzuM0hy1
-Fvn619o3I5DsWrfOz9t/QuznoOBw4PfzDPNT7VlzZN4xHAcr5+7B+DH9IsvlCt5N
-kQFuYpFZCpXNaD2XOtmIqjTCeLNfcgTEj0qoUIEKyKbBIgfP+7S2tLXy8JKUTy5g
-9kxXQeHueLykQ4Mt18JH0nMHbHbQl0K3LGT4ucRDOmjNtlQCltVLkIk3GimyqKs/
-vdZ9c+dm4Akx1qsJcwvveX+imJe2e9RUodcxWXxWrYnuPa5b5nfR1i+GfV0on/Pt
-AQ8gc9CkJpMiq5TQDOFhFP6yQcq77sXuUkEl5qamptedz28E0I693ulnfwcsE80p
-xkpIG6n33DZJSEyqgtWjE1P2pnsVfO5ILs3mKLe7bO1v3qMXcCkMCGH/kwzvtowq
-YvY4gaZMDZtQFY8U7lI9FdRUvVdeHAB24y291nhzABEBAAGJBYMEGAEKANNIFIAA
-AAAAFwAodmVyaWZpZWRAdG9ycHJvamVjdC5vcmdERjgxMTEwOUUxN0M4QkYxMzRC
-NUVFQjY4REM0M0EyODQ4ODIxRTMyTxSAAAAAAB4AKGJyaWRnZXNAYnJpZGdlcy50
-b3Jwcm9qZWN0Lm9yZ0RGODExMTA5RTE3QzhCRjEzNEI1RUVCNjhEQzQzQTI4NDg4
-MjFFMzIqGmh0dHBzOi8vYnJpZGdlcy50b3Jwcm9qZWN0Lm9yZy9wb2xpY3kudHh0
-AhsCBQJUigTTBQkDw01SAqTB2CAEGQEKAIEFAlIv8oFPFIAAAAAAHgAoYnJpZGdl
-c0BicmlkZ2VzLnRvcnByb2plY3Qub3JnOUZFMzlEMUE3NDM4OTIyMzNCM0Y2NkYy
-MjFCNTU0RTk1OTM4RjREMCoaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2plY3Qub3Jn
-L3BvbGljeS50eHQACgkQIbVU6Vk49NDbPw/5ATe/T8+eaToC3v0TYNRH5nveQvzA
-WdnshD3lnvfsgDhbilwifKpc5LHKXU3rvb42HH2cu0ckuksdDTvICZD9cJjRq/F+
-Mzm0pNCAJg0pQnHaaWFQjw+CHYEoizai3S+iYxhNHeSdA6Ty7xm4+bHNf0Aqblbd
-6dKwq9EvjwAI6zZsAHtsmHRUMdrFwGdKae6CSchUT2JQFBPEWMhvzdpDGACWVaSP
-sxYKuYg9LgpswGcof+tprRjKRl8MtSh0ufjbVBlTeSKpL5Y+fcTRD3PI8w7Ocr3z
-jr6XpYG4SUNHsWwxyu/DTXg76Lk1/+BdaH25hDOAasLUOU7yRL8zD/c7M0FkGXdj
-r5I2DEEqwzJ9cPHWjpgb8N9fZLoPFP9JOmKGHINqxNe7TfwiTdD6uDKs/u/QK1U+
-o3iYBXBTREdopPUdBTM9wYRUhyGXTEKLhUP3MGpXYlgeYPrSdp76VyN3BzLTbMv+
-+7rxyKxL9cWYU0pnXHgPC5nyHX5nqXmhMnkxAD3Bnm8n9XDfgiyTDExqksEh2VXt
-yhVfLezylEP2fwtd8/mABBCsTjzZW6FRfRRAjUZWZGFpFg8no1x5JS9uiswRP5g1
-qHijNFWpGyTtJWl5VNd0d9+LtVUX1jRpDUpsjZcxqs3fsvw2p+H/zQ1wFvDrsoav
-hqOTq+AEnJc7ZG8JEI3EOihIgh4ych8P/3GTyWb29+43YVibbSPPvEv4gFqziC+9
-1p92FJ0V4XdaT7TW3qaZVp5edUNwB/jjF0SxBybwaMX2ZIGXOjnjF6/Zby4ynuTX
-vZkS1mKRA0KWupB3e9PSMY3ZtssnqpGna/+3qlpxtunW7HcW4nCF/f59WHhlVjaO
-MXjtuWj59yB56Dd1sNjwhcNCyp4/NpzGnRW97ZV3Pp4oqIOqcGzCQXkVPcnaqcOh
-Cs9vIDJlMtn/IWBzUGimuRllDSSVSWkYkyJcG2NUHUwgXYpLwQz7sScvmCPchf4K
-qarpX0FpkUDfqaVVuQ7A2XbPUAVFzIk930G1WzgOuOdg9vhWSEjou+SKrAoMz90w
-3xHwEvmPDTTVJQft9ytoRbwZkIPfzzhII3mr4agbORAfzDaj5g/f6CVRdg6D3ME1
-Etg9ZrfLgRY993g/arfIME6OOsiNcy5+PunN96Rw0o1xoD+97NmZuQrs/p4Mfn5o
-8EwXHutREhahin+3/SV3hz9ReeLYmClq+OVhjPzPdtwZsFoyQyUJoFVHPTuSdChZ
-FPaqN68FjlNMugmxnvski3ZDVT7pw3B6otjjaL3rr6q0PC2yhEb2ntb3IFUizHjn
-80SmfE1Bqwit7ZHu8r/Gt/0iecGk5h84VzSgiGZGF/7m1i5UMVlNSeWnsInGa5Su
-7HSzfMq+YmkzuQINBFIv8p4BEADTOLR5e5NKKRPpjCb4B/8YYkWh+orb70EogIZ6
-j5v8d/djLyhjqZ9BIkh41/hYKMwnsa4KkDkTaX0eNu3BFB2zGgZ1GSd7525ESxiq
-suXIlAg2pex7bysaFfua0nUx64tmaQm2XArdkj/wI0pbg+idWym3WQQmZLyTTbzl
-8rpTEtTt+S2m6z3EeAhEHuNFH16hEDUywlef3EotX3njuFiLqaNvnzUYDxhUvKd2
-2K1es1ggispgP+eb1bkMApxecf2rqmSUEcvsuTWip4oGZPBLGDQeNKHkCUVbj4wT
-yWDIRtto3wi+4CFPEVzw+htj1cQfTstPqUdG7NSOmLQggedoUdv7AJm4MJJiyEax
-l+IAf6Afwrrm3eOSv0PgoUxOrUb9vhIoL8ih8gtiqvQ9qYaRQfQA/w3Z0Su2Yfoc
-fQS8Uw99qG+oTgieG6F6ud8+hMZAYVZFqbU+ztzMyDE6h4Hflkt6VNJ0Hk0VoF38
-TTs77pHXXBbLD6SzR6tbNuR9r/lbmC8Qf2A1ZAThR0iuGhNRFtUPo28GxakxGdLZ
-9kHIxjl7EN/gsmYTwuEhr+yfNtLwtSH0ojeqbDmgufvgh+SITCtyNDAUspjrZYEt
-F0NHRpSom2NFVELMqMRydU/ncph1rGZgVp6/zVj6xIlhKmqj5P1y/9B0c4Tu1CzJ
-pkJ5wwARAQABiQLpBBgBCgDTSBSAAAAAABcAKHZlcmlmaWVkQHRvcnByb2plY3Qu
-b3JnREY4MTExMDlFMTdDOEJGMTM0QjVFRUI2OERDNDNBMjg0ODgyMUUzMk8UgAAA
-AAAeAChicmlkZ2VzQGJyaWRnZXMudG9ycHJvamVjdC5vcmdERjgxMTEwOUUxN0M4
-QkYxMzRCNUVFQjY4REM0M0EyODQ4ODIxRTMyKhpodHRwczovL2JyaWRnZXMudG9y
-cHJvamVjdC5vcmcvcG9saWN5LnR4dAIbDAUCVIoE4QUJA8NNQwAKCRCNxDooSIIe
-Mo7JEADDBtQpYxPhbj3MT0xpk96EDlon/5yHVf+cnk1pNisc+HkJsVe1nh7gAWOz
-wJKdeqOVpgxiJTxIQdl6mipKwwFi0DreP7h56s1WQkuSSWJzqssAwWHfVAsX13fV
-zWd0XyxN/OF9ZKQjX4qwpJ/na631PSwZLvHYhMaZnb9pjNwC5/PEKRmFqLbQT6Px
-12miZT6ToPDCczHxJ4BxbEGVU+PtRsHwmTRT3JhxFNDfeVd+uwsQIMidJbUoqVW7
-fe2zNd0TaWyz4Rw087oZE2OXdctjvtsu8fzXx6d/tkazI6cUOqoaMTR41KEu5X0T
-BpWSAMADBYjNs9QRWXX7ZlsJRUSCX1EKbMhgoL6KIGceIkjH61M/LF6HqDgSgSWt
-h+LIYGa+LrB/6819o32QSOSHHJ5+NJrbCSaLgKE/LKnf92V2QbZE8IGY6EOSjHqn
-n1+j+CLRKY/kUyvk+1TumTghjg/aDs/8Jv8PvgSWLQ0q1rxHYbX7q9ZJhYC/4LdR
-ya/Cho6w2l0N3tV/IMAwvFNHsaiIiiwfoOQbkBUvkyzBwjKt96Ai4I0QKt/63uH0
-drQhlJEgIyGkOrorBByVqZAQdnoLENYIu6tDUj0bTbGObKqua4iPlSK3/g40zCm4
-9OgcN7A8kFuNpgp2EHqj1/jrwd7mZYKsWTuGiR/7fwXf+4xbvg==
-=raCx
------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(a)bridges.torproject.org>
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-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
-ILUXBkpIDfVSoZD7qWlntai53BDQr5pfMJhv15di4XAhtqv43vAmA57ifd+QJS2U
-AfYc4CdX0lk2BZ4jRD8jCZ4Uxw15E3RqhnXsWDRxtD4fwsb2ZFi0DDuPlwBdGgh5
-Rm2Bz9JjSV6gDEuXr/JtAzjSz1Jdh8wPkSofiHGTfxysVhlGlg+YPRziRlzML8A2
-0xY+9mPxEEin5ZQ9wmrDyiiOBvPTbG3O9+Sp5VZDuD4ivW/DHumPWGVSRdjcAQDe
-HMXUVGjhBDnj06XNrgJPhODdJeYq0EnGTt15ofZQSswD7TTTRPDOn0Cz/QARAQAB
-tDpCcmlkZ2VEQiAoT2ZmbGluZSBJRCBLZXkpIDxicmlkZ2VzQGJyaWRnZXMudG9y
-cHJvamVjdC5vcmc+iQkfBBMBCgEJBQJSWQfkSBSAAAAAABcAKHZlcmlmaWVkQHRv
-cnByb2plY3Qub3JnN0I3ODQzNzAxNUU2M0RGNDdCQjEyNzBBQ0JEOTdBQTI0RThF
-NDcyRU8UgAAAAAAeAChicmlkZ2VzQGJyaWRnZXMudG9ycHJvamVjdC5vcmc3Qjc4
-NDM3MDE1RTYzREY0N0JCMTI3MEFDQkQ5N0FBMjRFOEU0NzJFKhpodHRwczovL2Jy
-aWRnZXMudG9ycHJvamVjdC5vcmcvcG9saWN5LnR4dAIbAQMLDQkEFQoJCAQWAgEA
-Ah4BAheAJxhodHRwczovL2JyaWRnZXMudG9ycHJvamVjdC5vcmcva2V5LmFzYwAK
-CRDL2XqiTo5HLoqEP/48rFpJCVStn8xo+KkHSVvsqpxDRlb/nNheI+ov2UxILdwl
-NIU6kLsvKECKPe1AHKdS/MzANbkTF35Y4QgZsNpVXaCVL7adGBSzOdPFupDJJVOu
-wa+uFRc/FuNJyH/TIn56/+R5J5C54OxIYNxvW3WF4eHKLJYk/JZOMMfy4iWm7Sql
-0nDC5O435nK4F4Jb4GLPlUIzioIy2OWqGoFHXymbGhL1tWaqasYmED4n3AMqlYw6
-xnNhdWOc/KZelPl9nanybyh0IIdZqUKZleRt4BxSgIT8FqC2sZuZ8z7O9s987Naz
-Q32SKaP4i2M9lai/Y2QYfKo+wlG+egmxtujz7etQMGlpgBZzFLdJ8/w4U11ku1ai
-om74RIn8zl/LHjMQHnCKGoVlscTI1ZPt+p+p8hO2/9vOwTR8y8O/3DQSOfTSipwc
-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
-YnJpZGdlc0BicmlkZ2VzLnRvcnByb2plY3Qub3JnREY4MTExMDlFMTdDOEJGMTM0
-QjVFRUI2OERDNDNBMjg0ODgyMUUzMioaaHR0cHM6Ly9icmlkZ2VzLnRvcnByb2pl
-Y3Qub3JnL3BvbGljeS50eHQACgkQjcQ6KEiCHjIaqBAA0BuEs7horx6iCq4cjAhv
-YPLrxuC4fKEfVyhAjCJMJSFFCPAlGgU+BjyPNDD57wzKAmUkdJG+Ss25mwWXa53w
-5R2kDqDnHocOdZGtxZ7zx/uUd2eWLNBfVuK7nHOk1d1Hs0OZBnckc+MCqnLtuYe5
-68pa9+jW6cNIjAnzMIListmoXWgYYWJvMKeBMG4DGtYJ8w7CJQjOHc5yar12DrX3
-wnQ7hXtFuuqQblpEUnLnZGvHf2NKMZfBBMcP96h9OmLGNa+vmNYsMyPKU7n5hPgX
-nTgmQ4xrv1G7JukjppZRA8SFoxupcaQeTixyWERGBhBiAbwZsbQz8L/TVZKierzg
-sdNngHcFzE8MyjuJDvTos7qXPmgSRXFqJLRn0ZxpR5V1V8BVZUqCGuSZT89TizsD
-z5vyv8c9r7HKD4pRjw32P2dgcEqyGRkqERAgSuFpObP+juty+kxYyfnadBNCyjgP
-s7u0GmsTt4CZi7BbowNRL6bynrwrmQI9LJI1bPhgqfdDUbqG3HXwHz80oRFfKou8
-JTYKxK4Iumfw2l/uAACma5ZyrwIDBX/H5XEQqch4sORzQnuhlTmZRf6ldVIIWjdJ
-ef+DpOt12s+cS2F4D5g8G6t9CprCLYyrXiHwM/U8N5ywL9IeYKSWJxa7si3l9A6o
-ZxOds8F/UJYDSIB97MQFzBo=
-=JdC7
------END PGP PUBLIC KEY BLOCK-----
-"""
diff --git a/bridgedb/test/email_helpers.py b/bridgedb/test/email_helpers.py
index edc8196..cd805f9 100644
--- a/bridgedb/test/email_helpers.py
+++ b/bridgedb/test/email_helpers.py
@@ -25,11 +25,6 @@ from . import util
EMAIL_DIST = True
EMAIL_ROTATION_PERIOD = "1 day"
EMAIL_INCLUDE_FINGERPRINTS = True
-EMAIL_GPG_SIGNING_ENABLED = True
-EMAIL_GPG_HOMEDIR = '.gnupg'
-EMAIL_GPG_PRIMARY_KEY_FINGERPRINT = '0017098C5DF4197E3C884DCFF1B240D43F148C21'
-EMAIL_GPG_PASSPHRASE = None
-EMAIL_GPG_PASSPHRASE_FILE = None
EMAIL_DOMAIN_MAP = {
'googlemail.com': 'gmail.com',
'mail.google.com': 'gmail.com',
@@ -56,11 +51,6 @@ TEST_CONFIG_FILE = io.StringIO("""\
EMAIL_DIST = %s
EMAIL_ROTATION_PERIOD = %s
EMAIL_INCLUDE_FINGERPRINTS = %s
-EMAIL_GPG_SIGNING_ENABLED = %s
-EMAIL_GPG_HOMEDIR = %s
-EMAIL_GPG_PRIMARY_KEY_FINGERPRINT = %s
-EMAIL_GPG_PASSPHRASE = %s
-EMAIL_GPG_PASSPHRASE_FILE = %s
EMAIL_DOMAIN_MAP = %s
EMAIL_DOMAIN_RULES = %s
EMAIL_DOMAINS = %s
@@ -78,11 +68,6 @@ EMAIL_PORT = %s
""" % (repr(EMAIL_DIST),
repr(EMAIL_ROTATION_PERIOD),
repr(EMAIL_INCLUDE_FINGERPRINTS),
- repr(EMAIL_GPG_SIGNING_ENABLED),
- repr(EMAIL_GPG_HOMEDIR),
- repr(EMAIL_GPG_PRIMARY_KEY_FINGERPRINT),
- repr(EMAIL_GPG_PASSPHRASE),
- repr(EMAIL_GPG_PASSPHRASE_FILE),
repr(EMAIL_DOMAIN_MAP),
repr(EMAIL_DOMAIN_RULES),
repr(EMAIL_DOMAINS),
@@ -150,10 +135,10 @@ class DummyEmailDistributorWithState(DummyEmailDistributor):
:exc:`bridgedb.distributors.email.distributor.IgnoreEmail` on the third.
Note that the state tracking is done in a really dumb way. For example, we
- currently don't consider requests for help text or GnuPG keys to be a
- "real" request, so in the real email distributor they won't trigger either
- a TooSoonEmail or IgnoreEmail. Here we only track the total number of
- *any* type of request per client.
+ currently don't consider requests for help text to be a "real" request, so
+ in the real email distributor they won't trigger either a TooSoonEmail or
+ IgnoreEmail. Here we only track the total number of *any* type of request
+ per client.
"""
def __init__(self, *args, **kwargs):
diff --git a/bridgedb/test/test_crypto.py b/bridgedb/test/test_crypto.py
index 45c06ae..f57d4f3 100644
--- a/bridgedb/test/test_crypto.py
+++ b/bridgedb/test/test_crypto.py
@@ -91,143 +91,6 @@ class GetKeyTests(unittest.TestCase):
% (binascii.hexlify(key).decode('utf-8'), binascii.hexlify(SEKRIT_KEY).decode('utf-8')))
-class InitializeGnuPGTests(unittest.TestCase):
- """Unittests for :func:`bridgedb.crypto.initializeGnupG`."""
-
- def _moveGnuPGHomedir(self):
- """Move the .gnupg/ directory from the top-level of this repo to the
- current working directory.
-
- :rtype: str
- :returns: The full path to the new gnupg home directory.
- """
- here = os.getcwd()
- topDir = here.rstrip('_trial_temp')
- gnupghome = os.path.join(topDir, '.gnupg')
- gnupghomeNew = os.path.join(here, '.gnupg')
-
- if os.path.isdir(gnupghomeNew):
- shutil.rmtree(gnupghomeNew)
-
- shutil.copytree(gnupghome, gnupghomeNew)
-
- return gnupghomeNew
-
- def _writePassphraseToFile(self, passphrase, filename):
- """Write **passphrase** to the file at **filename**.
-
- :param str passphrase: The GnuPG passphase.
- :param str filename: The file to write the passphrase to.
- """
- fh = open(filename, 'w')
- fh.write(passphrase)
- fh.flush()
- fh.close()
-
- def setUp(self):
- """Create a config object and setup our gnupg home directory."""
- self.config = _createConfig()
- self.gnupghome = self._moveGnuPGHomedir()
- self.config.EMAIL_GPG_HOMEDIR = self.gnupghome
-
- self.passphraseFile = 'gpg-passphrase-file'
- self._writePassphraseToFile('sekrit', self.passphraseFile)
-
- def test_crypto_initializeGnuPG(self):
- """crypto.initializeGnuPG() should return a 2-tuple with a gpg object
- and a signing function.
- """
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNotNone(gpg)
- self.assertIsNotNone(signfunc)
-
- def test_crypto_initializeGnuPG_disabled(self):
- """When EMAIL_GPG_SIGNING_ENABLED=False, crypto.initializeGnuPG()
- should return a 2-tuple of None.
- """
- self.config.EMAIL_GPG_SIGNING_ENABLED = False
- gpg, signfunc = crypto.initializeGnuPG(self.config)
-
- self.assertIsNone(gpg)
- self.assertIsNone(signfunc)
-
- def test_crypto_initializeGnuPG_no_secrets(self):
- """When the secring.gpg is missing, crypto.initializeGnuPG() should
- return a 2-tuple of None.
- """
- secring = os.path.join(self.gnupghome, 'secring.gpg')
- if os.path.isfile(secring):
- os.remove(secring)
-
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNone(gpg)
- self.assertIsNone(signfunc)
-
- def test_crypto_initializeGnuPG_no_publics(self):
- """When the pubring.gpg is missing, crypto.initializeGnuPG() should
- return a 2-tuple of None.
- """
- pubring = os.path.join(self.gnupghome, 'pubring.gpg')
- if os.path.isfile(pubring):
- os.remove(pubring)
-
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNone(gpg)
- self.assertIsNone(signfunc)
-
- def test_crypto_initializeGnuPG_with_passphrase(self):
- """crypto.initializeGnuPG() should initialize correctly when a
- passphrase is given but no passphrase is needed.
- """
- self.config.EMAIL_GPG_PASSPHRASE = 'password'
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNotNone(gpg)
- self.assertIsNotNone(signfunc)
-
- def test_crypto_initializeGnuPG_with_passphrase_file(self):
- """crypto.initializeGnuPG() should initialize correctly when a
- passphrase file is given but no passphrase is needed.
- """
- self.config.EMAIL_GPG_PASSPHRASE_FILE = self.passphraseFile
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNotNone(gpg)
- self.assertIsNotNone(signfunc)
-
- def test_crypto_initializeGnuPG_missing_passphrase_file(self):
- """crypto.initializeGnuPG() should initialize correctly if a passphrase
- file is given but that file is missing (when no passphrase is actually
- necessary).
- """
- self.config.EMAIL_GPG_PASSPHRASE_FILE = self.passphraseFile
- os.remove(self.passphraseFile)
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNotNone(gpg)
- self.assertIsNotNone(signfunc)
-
- def test_crypto_initializeGnuPG_signingFunc(self):
- """crypto.initializeGnuPG() should return a signing function which
- produces OpenPGP signatures.
- """
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNotNone(gpg)
- self.assertIsNotNone(signfunc)
-
- sig = signfunc("This is a test of the public broadcasting system.")
- print(sig)
- self.assertIsNotNone(sig)
- self.assertTrue(sig.startswith(b'-----BEGIN PGP SIGNED MESSAGE-----'))
-
- def test_crypto_initializeGnuPG_nonexistent_default_key(self):
- """When the key specified by EMAIL_GPG_PRIMARY_KEY_FINGERPRINT doesn't
- exist in the keyrings, crypto.initializeGnuPG() should return a 2-tuple
- of None.
- """
- self.config.EMAIL_GPG_PRIMARY_KEY_FINGERPRINT = 'A' * 40
- gpg, signfunc = crypto.initializeGnuPG(self.config)
- self.assertIsNone(gpg)
- self.assertIsNone(signfunc)
-
-
class RemovePKCS1PaddingTests(unittest.TestCase):
"""Unittests for :func:`bridgedb.crypto.removePKCS1Padding`."""
diff --git a/bridgedb/test/test_email_autoresponder.py b/bridgedb/test/test_email_autoresponder.py
index d5023e0..9b49c67 100644
--- a/bridgedb/test/test_email_autoresponder.py
+++ b/bridgedb/test/test_email_autoresponder.py
@@ -35,16 +35,8 @@ from bridgedb.test.email_helpers import DummyEmailDistributorWithState
class CreateResponseBodyTests(unittest.TestCase):
"""Tests for :func:`bridgedb.distributors.email.autoresponder.createResponseBody`."""
- def _moveGPGTestKeyfile(self):
- here = os.getcwd()
- topDir = here.rstrip('_trial_temp')
- self.gpgFile = os.path.join(topDir, '.gnupg', 'TESTING.subkeys.sec')
- self.gpgMoved = os.path.join(here, 'TESTING.subkeys.sec')
- shutil.copy(self.gpgFile, self.gpgMoved)
-
def setUp(self):
"""Create fake email, distributor, and associated context data."""
- self._moveGPGTestKeyfile()
self.toAddress = "user(a)example.com"
self.config = _createConfig()
self.ctx = _createMailServerContext(self.config)
@@ -62,13 +54,6 @@ class CreateResponseBodyTests(unittest.TestCase):
]
return lines
- def test_createResponseBody_getKey(self):
- """A request for 'get key' should receive our GPG key."""
- lines = self._getIncomingLines()
- lines[4] = "get key"
- ret = autoresponder.createResponseBody(lines, self.ctx, self.toAddress)
- self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', ret)
-
def test_createResponseBody_bridges_invalid(self):
"""An invalid request for 'transport obfs3' should still return
bridges."""
diff --git a/bridgedb/test/test_email_request.py b/bridgedb/test/test_email_request.py
index e0bb642..1cbcbc0 100644
--- a/bridgedb/test/test_email_request.py
+++ b/bridgedb/test/test_email_request.py
@@ -27,32 +27,21 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
def test_determineBridgeRequestOptions_multiline_invalid(self):
lines = ['',
'help',
- 'i need bridges',
- 'give me your gpgs']
+ 'i need bridges']
reqvest = request.determineBridgeRequestOptions(lines)
# We consider every request valid...
self.assertEqual(reqvest.isValid(), True)
- self.assertFalse(reqvest.wantsKey())
# ...so by default, we return a bridge.
self.assertEqual(len(reqvest.transports), 1)
- def test_determineBridgeRequestOptions_get_key(self):
- """Requesting 'get key' should raise EmailRequestedKey."""
- lines = ['',
- 'get key']
- self.assertRaises(request.EmailRequestedKey,
- request.determineBridgeRequestOptions, lines)
-
def test_determineBridgeRequestOptions_multiline_invalid(self):
"""Requests without a 'get' are incorrect but still valid, and should
return bridges."""
lines = ['',
'transport obfs3',
- 'ipv6 vanilla bridges',
- 'give me your gpgs']
+ 'ipv6 vanilla bridges']
reqvest = request.determineBridgeRequestOptions(lines)
self.assertEqual(reqvest.isValid(), True)
- self.assertFalse(reqvest.wantsKey())
# Though they did request IPv6, technically.
self.assertIs(reqvest.ipVersion, 6)
# And they did request a transport, technically.
@@ -67,7 +56,6 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
reqvest = request.determineBridgeRequestOptions(lines)
# It's valid because it included a 'get'.
self.assertEqual(reqvest.isValid(), True)
- self.assertFalse(reqvest.wantsKey())
# Though they didn't request IPv6, so it should default to IPv4.
self.assertIs(reqvest.ipVersion, 4)
# And they requested two transports.
@@ -90,7 +78,6 @@ class DetermineBridgeRequestOptionsTests(unittest.TestCase):
reqvest = request.determineBridgeRequestOptions(lines)
# It's valid because it included a 'get'.
self.assertEqual(reqvest.isValid(), True)
- self.assertFalse(reqvest.wantsKey())
# Though they didn't request IPv6, so it should default to IPv4.
self.assertIs(reqvest.ipVersion, 4)
# And they requested two transports.
@@ -156,25 +143,6 @@ class EmailBridgeRequestTests(unittest.TestCase):
self.request.isValid(False)
self.assertEqual(self.request.isValid(), False)
- def test_EmailBridgeRequest_wantsKey_initial(self):
- """Initial value of EmailBridgeRequest.wantsKey() should be False."""
- self.request.wantsKey(None)
- self.assertEqual(self.request.wantsKey(), False)
-
- def test_EmailBridgeRequest_wantsKey_True(self):
- """The value of EmailBridgeRequest.wantsKey() should be True, after it
- has been called with ``True`` as an argument.
- """
- self.request.wantsKey(True)
- self.assertEqual(self.request.wantsKey(), True)
-
- def test_EmailBridgeRequest_wantsKey_False(self):
- """The value of EmailBridgeRequest.wantsKey() should be False, after
- it has been called with ``False`` as an argument.
- """
- self.request.wantsKey(False)
- self.assertEqual(self.request.wantsKey(), False)
-
def test_EmailBridgeRequest_withIPv6(self):
"""IPv6 requests should have ``ipVersion == 6``."""
self.assertEqual(self.request.ipVersion, 4)
diff --git a/bridgedb/test/test_email_templates.py b/bridgedb/test/test_email_templates.py
index 4a5979d..a948c91 100644
--- a/bridgedb/test/test_email_templates.py
+++ b/bridgedb/test/test_email_templates.py
@@ -30,10 +30,6 @@ class EmailTemplatesTests(unittest.TestCase):
self.t = NullTranslations(StringIO('test'))
self.client = Address('blackhole(a)torproject.org')
self.answer = 'obfs3 1.1.1.1:1111\nobfs3 2.2.2.2:2222'
- # This is the fingerprint of BridgeDB's offline, certification-only
- # GnuPG key. It should be present in any responses to requests for our
- # public keys.
- self.offlineFingerprint = '7B78437015E63DF47BB1270ACBD97AA24E8E472E'
def shouldIncludeCommands(self, text):
self.assertSubstring('commands', text)
@@ -51,9 +47,6 @@ class EmailTemplatesTests(unittest.TestCase):
def shouldIncludeAutomationNotice(self, text):
self.assertSubstring('automated email', text)
- def shouldIncludeKey(self, text):
- self.assertSubstring('-----BEGIN PGP PUBLIC KEY BLOCK-----', text)
-
def test_templates_addCommands(self):
text = templates.addCommands(self.t)
self.shouldIncludeCommands(text)
@@ -76,10 +69,6 @@ class EmailTemplatesTests(unittest.TestCase):
self.shouldIncludeAutomationNotice(text)
self.shouldIncludeCommands(text)
- def test_templates_buildKeyMessage(self):
- text = templates.buildKeyMessage(self.t, self.client)
- self.assertSubstring(self.offlineFingerprint, text)
-
def test_templates_buildSpamWarning(self):
text = templates.buildSpamWarning(self.t, self.client)
self.shouldIncludeGreeting(text)
diff --git a/bridgedb/test/test_main.py b/bridgedb/test/test_main.py
index 82b609f..64b65a4 100644
--- a/bridgedb/test/test_main.py
+++ b/bridgedb/test/test_main.py
@@ -444,11 +444,6 @@ EMAIL_BIND_IP = "127.0.0.1"
EMAIL_PORT = 55557
EMAIL_N_BRIDGES_PER_ANSWER = 3
EMAIL_INCLUDE_FINGERPRINTS = True
-EMAIL_GPG_SIGNING_ENABLED = False
-EMAIL_GPG_HOMEDIR = '../.gnupg'
-EMAIL_GPG_PRIMARY_KEY_FINGERPRINT = '0017098C5DF4197E3C884DCFF1B240D43F148C21'
-EMAiL_GPG_PASSPHRASE = None
-EMAIL_GPG_PASSPHRASE_FILE = None
HTTPS_SHARE = 10
EMAIL_SHARE = 5
RESERVED_SHARE = 2"""
diff --git a/requirements.txt b/requirements.txt
index ef72ed5..79bb01d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@ html5lib==1.0b8
Mako==1.1.1
pycryptodome==3.9.6
Twisted==20.3.0
-gnupg==2.3.1
ipaddr==2.2.0
Pillow==6.2.2
pyOpenSSL==19.1.0
diff --git a/scripts/setup-tests b/scripts/setup-tests
index 1de3c71..fc89d8f 100755
--- a/scripts/setup-tests
+++ b/scripts/setup-tests
@@ -13,7 +13,7 @@ cd $THERE
mkdir -p run/from-authority
mkdir -p run/from-bifroest
-cp -R -t run bridgedb.conf captchas .gnupg
+cp -R -t run bridgedb.conf captchas
# Add '127.0.0.1' to EMAIL_DOMAINS in bridgedb.conf. This should ONLY be
# done on testing servers, never on production servers.
sed -r -i -e "s/(EMAIL_DOMAINS)(.*)(])/\1\2\, '127.0.0.1']/" run/bridgedb.conf
1
0

27 May '20
commit 4cdd6a61d01ae6d7c755e870acd8a7eb139d22e7
Merge: 208b49c b366bb4
Author: Philipp Winter <phw(a)nymity.ch>
Date: Wed Apr 15 09:34:59 2020 -0700
Merge branch 'defect/17548' into develop
.gnupg/TESTING.pub | Bin 4622 -> 0 bytes
.gnupg/TESTING.subkeys.sec | Bin 7212 -> 0 bytes
.gnupg/bridgedb-offline-key.pub.asc | 113 ----------
.gnupg/bridgedb-online-key.pub.asc | 100 ---------
.gnupg/gpg.conf | 96 ---------
.gnupg/pubring.gpg | Bin 4634 -> 0 bytes
.gnupg/secring.gpg | Bin 7224 -> 0 bytes
.travis.requirements.txt | 1 -
CHANGELOG | 6 +
README.rst | 29 +--
bridgedb.conf | 45 ----
bridgedb/configure.py | 3 +-
bridgedb/crypto.py | 99 +--------
bridgedb/distributors/email/autoresponder.py | 41 +---
bridgedb/distributors/email/distributor.py | 6 +-
bridgedb/distributors/email/request.py | 22 --
bridgedb/distributors/email/server.py | 10 -
bridgedb/distributors/email/templates.py | 7 -
bridgedb/distributors/https/server.py | 2 -
bridgedb/distributors/https/templates/base.html | 2 -
bridgedb/i18n/templates/bridgedb.pot | 84 ++++----
bridgedb/strings.py | 268 +-----------------------
bridgedb/test/email_helpers.py | 23 +-
bridgedb/test/test_crypto.py | 137 ------------
bridgedb/test/test_email_autoresponder.py | 15 --
bridgedb/test/test_email_request.py | 36 +---
bridgedb/test/test_email_templates.py | 11 -
bridgedb/test/test_main.py | 5 -
requirements.txt | 1 -
scripts/setup-tests | 2 +-
30 files changed, 63 insertions(+), 1101 deletions(-)
1
0