GSoC 2017 - The point of no return
This week is around the halfway of GSoC 2017 project timeline, hence the title.
Key management#
As I set out to do, I have now implemented most of the after subscription key management. The key change
command. The pre subscription key management is done via a custom dynamically loaded subscription policy/workflow. This is possible with my pluggable-workflows
branch/MR which introduces dynamically loaded workflows, which subscription and unsubscription policies are a part of.
Subscription#
On subscription the PGP enabled mailing list needs a users public key. An example conversation establishing that follows (shows a list with moderation + pgp enabled subscription policy):
Mailman User ------- ---- list@example.com anne@example.com <- subscribe 1. 2. key set "token1" -> + instructions to reply and attach user key (signed by list) <- key set "token1" 3. (key attached as per RFC3156(PGP/MIME) or inline and we do our best to find it.) 4 key confirm "token2" -> + statement containing "token2" and user key fingerprint in body, with instructions to sign it (signed by list, encrypted to user key) <- key confirm "token2" 5. + must contain signed statement from step 4. (required to be signed by user key) 6. ... the rest of the subscription steps (moderation)...
Steps 3 and 5 can be optionally encrypted to the list key.
This workflow gives “some” assurance that the user really has the key she is subscribing with, however the trust in the address/user/key has to come from the list moderator and both my proposal and implementation rely on that. This workflow only proves that Mailman is communicating with someone that has the user key (can decrypt "token2"
and sign the statement
), not that that user is anne@example.com
.
Key change#
Works similar to the key set
command on subscription. Works via a custom workflow, but not a subscription workflow/policy, just a workflow.
Mailman User ------- ---- list@example.com anne@example.com <- key change 1. (new! key attached as per RFC3156(PGP/MIME) or inline and we do our best to find it.) 2. key confirm "token1" -> + statement containing "token1" and new! user key fingerprint in body, with instructions to sign it (signed by list, encrypted to new! user key) <- key confirm "token1" 3. + must contain signed statement from step 2. (required to be signed by old! user key)
Steps 1 and 3 can again be optionally encrypted.
This ensures that only someone with possesion of the old user key can change it. It requires the user to decrypt with the new key and sign a statement with the new key fingerprint as well as the token in it with the old key.
PyPi package#
mailman-pgp @ PyPi I have now created a PyPi package for the mailman-pgp plugin as it’s maturing, and while still unusable I wanted the name.
Test coverage#
I got test coverage of mailman-pgp to 95% which now actually means something as large parts of the codebase are implemented and not just stubs. Since this plugin requires features not merged into Mailman Core (or PGPy) for pipelines to work I maintain forks of both with branches that merge all required branches into a plugin
branch for Mailman Core and dev
branch for PGPy.
Next up#
Outgoing#
I had a look at working in outgoing encryption of messages for pgp enabled mailing lists. Encryption cannot be done as a handler, as it requires to process the messages per-recipient or per-batch of recipients. The only configurable/dynamic option currently in Mailman Core is the [mta].outgoing
callable. Which is not ideal since it itself has more functionality than simply dispatching to a correct Delivery
instance based on the list configuration, that would have to be duplicated in mailman-pgp. The IMailTransportAgentDelivery
interface looks promising though, so I’m thinking about refactoring the outgoing callable a bit to allow setting a custom one without the duplicities.
Signature hash tracking#
To prevent replay attacks for things where always sending and requiring a signed confirmation token in response is not practically doable, the pgp plugin will keep signature hashes with timestamps and posssibly key fingerprints in a DB/some other quickly searchable structure, and will check signatures it receives against the hashes in that structure. It will then act accordingly, for example not allowing a user to post the same message (with the same signature) again, since it could have been replayed.
Documentation#
I wanted to get the pgpmailman-proposal repository updated with current state/MRs but didn’t get to it this week, so might find time for it over the weekend as well as for some code documentation.