[Mailman-Developers] [GSoC] Encrypted mailing lists - update v5

Jan Jancar johny at neuromancer.sk
Mon Jun 12 15:35:47 EDT 2017

Hi all.

Sending an update here along with a new blog post.

 GSoC 2017 - About the plugin

As last time I described outstanding PRs to Mailman Core and other
Mailman's components, this time I am going to describe the plugin I am
building on top of those components to enable PGP encrypted mailing lists.

In fact there are two plugins to present, with the first one being a
general and quick plugin example that showcases how the new plugin API
might be used and also provides some nice services for the PGP plugin.

[repo @ gitlab](https://gitlab.com/J08nY/mailman-rest-events)

This plugin subscribes itself to receive events in Mailman Core and
sends them to urls configured. It is a variation of what
[mailman!264](https://gitlab.com/mailman/mailman/merge_requests/264) is
intending to do, based on the plugin API implemented in my MRs. It
currently offers only basic functionality, a URL is specified in config
per `endpoint` along with an API key (very similar to
mailman-hyperkitty) and a regex of event class names that will be sent.
The data sent currently is only the event class name in a JSON object.
Config can have many `endpoints` specified with the form shown below.

url: http://localhost/django/api
api_key: Something_secret_here
events: .*

Results in a call such as this one:

POST /django/api?key=Something_secret_here HTTP/1.1
Content-Type: application/json

{"event": "DomainCreatedEvent"}

The plugin is currently very bare bones and proper serialization of
events is underway. I am thinking of recursively serializing the
non-private event attributes until an easily serializable object is
reached, such as an `Address` or a `MailingList` or anything that has a
unique string associated with it and can be queried using the REST API
and such a string. So for example:

  "name": "DomainCreatedEvent",
  "event": {
    "domain": "example.com"


  "name": "AddressVerificationEvent",
  "event": {
    "address": "anne at example.org"

This plugin will be used by the mailman-pgp plugin to send events to
django-mailman3 which will distribute them to Postorius, HyperKitty and
the django app created to enable PGP encrypted mailing lists.

[repo @ gitlab](https://gitlab.com/J08nY/mailman-pgp)

First of all, I think I came up with a name that better fits with
mailman-hyperkitty being an archiver "plugin" and in general with how
plugins for projects are named in python (flask_ext_... and so on).

As the general functionality and layout of the plugin was already
described I will mostly just summarise issues I am currently working on

low level PGP work
I originally proposed using python-pgp
https://pypi.python.org/pypi/py-pgp/0.0.1) to use to parse and create
OpenPGP packets, as other libraries mostly offer only a high-level API
or are not so feature rich. However this library seems quite
un-maintained, so either a working fork should be established or a
different library used. I am currently looking at both options. Will
contact the original author as well as the current pypi package owner
and see what's possible.

public key on subscription
Since a PGP enabled mailing list needs to know the public key of a
subscribed address at the point when moderator approval is required,
some mechanism to do so is necessary. This needs to happen before
moderator approval, as the moderator / list owner should be able to see
/ download the provided key to verify it (or at least its fingerprint).
Currently I see two options, an extension of the proposed key command or
some changes to the current Subscription and Unsubscription workflows.

Extending the proposed key command would let the user use said command
to send and confirm his public key, before a subscription to an
encrypted list. This is similar to how schleuder does it. They
essentially run somewhat of a mailing key-server where the users might
submit keys via custom headers in message body.

However the current `SubscriptionWorkflow` and `UnsubscriptionWorkflow`
are really close to being able to require a custom additional step
during which the subscribers key is received and confirmed. Maybe making
`[Un]SubscriptionWorkflow` pluggable components, that can be set on a
per-list basis, similar to owner/posting chains or pipelines.

The second solution is definitely a more heavy-handed one, although
might be a better one in the long run. As it allows plugins to provide
[un]subscription steps which might be a nice use for plugins in Mailman
Core. I can imagine for example subscription verification where the
plugin verifies that the subscriber is a customer of some company by
showing the user a confirmation token in the customer system etc..

require confirmation for all commands
To address replay attacks where an attacker listens on a user performing
a command by sending it to the `list_id-confirm` address and then sends
the same message again in the future to replay the command, all commands
will need to require confirmation. This stops the attacker since he
cannot obtain the cleartext of the message containing the confirmation
token, or even if he could, he cannot forge the signature on the
confirmation message (leaving endpoint security out-of-scope). To reuse
the `confirm` command, Workflows and confirmation would have to be
refactored out from subscription management.

   /\  # PGP: 362056ADA8F2F4E421565EF87F4A448FE68F329D
  /__\  # https://neuromancer.sk
 /\  /\  # Eastern Seaboard Phishing Authority
/__\/__\  #

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 862 bytes
Desc: OpenPGP digital signature
URL: <http://mail.python.org/pipermail/mailman-developers/attachments/20170612/3c752ad9/attachment.sig>

More information about the Mailman-Developers mailing list