This patch is an effort to include gpg support in mailman. Additional requirements: gpg binary in path of qrunner. GnuPGInterface python library from http://py-gnupg.sourceforge.net/ A quick howto: Set up the patched mailman. Create a list. Go to the admin menu. Open "Privacy options", select "GPG options". Make the settings appropriate for your list (yes, there is some help text!). Create a keypair for your list. Make sure the list-posting-address is in one of the keys identities. Publish the public key for your list, e.g. on the list info page. Ask all subscribers to upload their public key. A good idea is to set up the web interface to only run over https. Some notes: I only updated the english html template for the user preferences; that means that users using a different language setting will be unable to upload their public key. Either allow English only, or make the patches to other language templates (and send the diff to me). Users _won't get warnings_ when mails are not delivered to them due to the encryption send policy. Failures to send due to a missing public key will be treated like bounces. There certainly are several issues, bugs, etc. - see the webpage mentioned below for the current status (known bugs, wishlist). About the patch: The mm_cfg.py file of this distribution is already patched to support gpg. Per default, all lists behave as before, i.e. gpg is disabled by default. Necessary for GPG support: DELIVERY_MODULE = 'GpgSMTPDirect' Include 'GpgDecrypt' in all pipelines after 'Replybot' GPG support needs to store additional information for the mailing lists, thus new variables were introduced. Have a look at bin/update and search for "GPG". The automatic upgrade procedure occuring on a change of the version number is implemented yet untested. You can either modify the version number in Version.py to trigger the automatic patch, or run bin/update --force (worked for me, but I won't give any guarantees). The current status of this patch is documented on http://medien.informatik.uni-ulm.de/~stefan/gpg-mailman.html Please do send feedback! stefan.schlott@informatik.uni-ulm.de GPG Key ID 0x4841469F Happy encrypting! Stefan. ------------------------------------------------------------------------- Additions by Joost van Baal for the SURFnet Secure List Server project ====================================================================== This is Mailman patch #1167696 , see https://sourceforge.net/tracker/index.php?func=detail&aid=1167696&group_id=103&atid=300103 . The patch is discussed on the Mailman developers list, see http://mail.python.org/pipermail/mailman-developers/2005-February/017910.html . Usage ----- Next to Stefan's hints, please note the following: - Very likely, you'd prefer "Confirm and approve" as subscribe_policy (Privacy Options; Subscribtion Rules) - Very likely, you'd prefer "No" for archive (Archiving Options): no effort was made to do something "sane" w.r.t. the archiving of encrypted posts. Just don't archive. - Subscribers who do not upload their public keys will miss posts. Errors show up in /var/log/mailman/smtp-failure: Mar 24 15:29:28 2005 (5267) delivery to joe@example.com failed with code 550: Encryption forced, but no keys found - Tell your subscribers where to upload their keys: list Info Page, Subscribers section. Visit "Subscriber List", choose your address, list membership configuration, "Your GPG key for postings" - Distribute the list public key to your subscribers, e.g. by posting it to the list after they've subscribed, or by pasting it in "[General Options], info" in the list admin webinterface. Specs ----- This enhances Stefan's patch to: - A post will be distributed only if the PGP signature on the post is from one of the list members. - For sending encrypted email, a list member encrypts to the public key of the list. The post will be decrypted and re-encrypted to the public keys of all list members. (Later, the patch will handle RFC 2633 (S/MIME) messages too, next to RFC 2440 (OpenPGP)). In order to achieve this, each list has a public and private key, as well as a key passphrase. Furthermore, new list settings are defined: gpg_postings_allowed: Is it allowed to send to this list postings which are encrypted with the GPG list key? gpg_msg_distribution: Are subscribers allowed (or even forced) to upload their GPG public key in order to receive all messages encrypted? gpg_post_sign: Should posts be GPG signed with an acknowledged subscriber key before being distributed? gpg_msg_sign: Should the server sign encrypted messages? Finally, each subscriber can upload her PGP public key using the webinterface. TODO ---- - Do more testing. work /severity work is: easy, normal, difficult. severity is: wishlist, normal, critical. normal/crit Fatal error: shamir:/var/log/mailman/error Apr 26 13:22:11 2005 (23365) Uncaught runner exception: [Errno 32] Broken pipe Apr 26 13:22:11 2005 (23365) Traceback (most recent call last): File "/usr/lib/mailman/Mailman/Queue/Runner.py", line 111, in _oneloop self._onefile(msg, msgdata) File "/usr/lib/mailman/Mailman/Queue/Runner.py", line 167, in _onefile keepqueued = self._dispose(mlist, msg, msgdata) File "/usr/lib/mailman/Mailman/Queue/OutgoingRunner.py", line 73, in _dispose self._func(mlist, msg, msgdata) File "/usr/lib/mailman/Mailman/Handlers/GpgSMTPDirect.py", line 146, in process deliveryfunc(mlist, msg, msgdata, envsender, refused, conn) File "/usr/lib/mailman/Mailman/Handlers/GpgSMTPDirect.py", line 378, in verpdeliver ciphertext = gh.encryptSignMessage(plaintext,keyids) File "/var/lib/mailman/Mailman/GPGUtils.py", line 281, in encryptSignMessage p.handles['stdin'].close() IOError: [Errno 32] Broken pipe Apr 26 13:22:11 2005 (23365) SHUNTING: 1114514530.3134+8c6726072985dc472532b1f538236a4365743440 . Probably occurs when private key for list is missing, and: gpg_postings-allowed: Yes gpg_msg_distribution: Yes gpg_post_sign: Yes gpg_msg_sign: Yes normal/crit The "change global" toggle in the subscribers upload-your-public-key webgui box is broken: joostvb@shamir:~% gpg --homedir /var/lib/mailman/lists/ssls-private/gpg --fingerprint doesn't show the key. easy /normal Prepare translations for the 'upload pgp key' web thingie. Especially Dutch is needed. Users who have a non-english preferred language won't see this option now. diffic/critic Upgrade this patch to apply cleanly against mailman 2.1.6 which will be released at about 2005-04-18. normal/wish Bounce messages to posters ("Message has to be encrypted!") have same subject as post. That's better be: "Subject: Message rejected (was: foo)". ? /? Using the web roster, any subscriber can view any subscribers' preferences, including public key. And maybe even change. Can it? easy /normal Under some circumstances, uploading a bogus public subscriber key leads to posts being silently discarded (even the admin does not get a notification) if list has gpg_msg_distribution Force. easy /crit Remove all debug code: currently, it sends way to much stuff to syslog. ? /crit Fix copyright blurbs: GPGUtils.py probably has wrong FSF copyright statement. Biggest lumps of changes by me are in Mailman/GPGUtils.py (function verifyMessage added) and in Mailman/Handlers/Moderate.py (code which deals with gpg_post_sign added). I believe these are nontrivial so copyright-able. Check with specialist. Likely, Mailman upstream wants a copyright assignment to FSF before patch gets included. diffic/? Harden this thing: re-encrypt immediately after decrypting. This patch (re)encrypts _just_ before sending. easy /? GpgSMTPDirect.py could better be just a patch on SMTPDirect.py. Main diff is in ``def verpdeliver'' . normal/normal Merge more of my own docs with this patch. easy /crit Fix documentation: when creating a list, make sure the listadmin password is _not_ sent via plain email: Someone stealing the list admin passsword has access to the list private key. Therefore, create the list using the CLI, and transport password manually via secure channel. easy /normal Perhaps we should suggest an empty passphrase for list keys in our interface: The passphrase is stored in clear-text anyway. Perhaps even just remove the passphare textbox in the webgui. "You need a Passphrase to protect your secret key. You don't want a passphrase - this is probably a *bad* idea! I will do it anyway. You can change your passphrase at any time, using this program with the option "--edit-key". ? /normal Passphrase as supplied to webinterface cannot contain stuff which needs html-escaping. Workaround: use [:alphanum:] only. diffic/normal We should refuse to create an html list archive for secure lists. (Currently, the default for new lists is changed by this patch from do-archive to don't-archive.) normal/wish Perhaps we should enable fetching public keys from subscribers from OpenPGP keyservers. Pasting huge public keys can be a pita. ? /crit It seems we need a symlink /usr/lib/mailman/Mailman/GnuPGInterface.py -> /usr/lib/site-python/GnuPGInterface.py We might have to hack paths.py to fix this. normal/? It'd be nice if commandline interfaces and email interfaces could be used for configuring (some of the) gpg stuff too, e.g. for uploading public keys. ? /crit Member public keys should be importable from a database; therefore write CLI's. easy /crit Add ^L-thingies and other stuff from Mailman coders styleguide to this patch. diffic/? Add extra configuration toggle: some users might want to post signed, but receive unencrypted posts unencrypted. Currently, this is not possible. easy /crit (Perhaps a problem in the Debian package only: ) /var/log/mailman/gpg is not rotated. ? /wish If a list has: gpg_postings_allowed Yes (encrypt post to listkey) gpg_msg_distribution Force (distribute encypted) gpg_post_sign Force (should posts be signed) gpg_msg_sign Yes (distribute signed) and someone is subcribed without having uploaded her public key, then this person receives posts mangled: content-type header says us-ascii, while body is quoted-printable. diffic/? If a post is properly signed, accept it, no matter wether the From-adress is subscribed and no matter the sender moderation policy. ? /? Problems with umlauts aka inline-pgp-trouble - seems to be fixed, but requires additional testing ? /wish Inline PGP-mail with attachments - undefined results. Some mailers can produce this. :-( ? /? Deal with both inline (aka traditional) pgp signed/encrypted posts as well as pgpg/mime; test this. diffic/wish If the "force" policy is in effect: reject plaintext control e-mails that contain a command with a password - currently all unsigned control e-mails are accepted without question because subscribe requests are handled over this channel as well diffic/wish If the "force" policy is in effect: "fuzzy checking", that is, if only part of the e-mail is encrypted (with cleartext underneath the PGP block). Is there a need for this? diffic/crit Deal with subscribers without public keys: Notification e-mail to those who haven't uploaded a key; and/or: make a (CLI) interface to check for subscibers without keys, to be used by site- or list-admin. Under some circumstances, these subscribers receive all mail in clear-text, even the encrypted ones. diffic/wish When bouncing e-mail because list policy was violated (e.g., someone sent unencrypted e-mail to mailman even though encryption-policy="force"): only bounce the headers, not the complete e-mail message. diffic/wish Fix the way mails are sent out over SMTP: do chunking for encrypted e-mail too. see also http://mail.python.org/pipermail/mailman-developers/2005-February/017910.html . ? /crit All defaults should be strict: lists not visible on listinfo page, no roster, only listadmin can add members. Perhaps it's best to add this to install manual: system-admin, you should hack mm_cfg.py! normal/crit Write proper documentation for listadmins and subscribers. diff /crit Try to make this patch clean, in order to get it into upstream Mailman (or the Mailman Debian package). diff /wish When re-encrypting a signed message, the original signature gets lost: this makes it possible for one list member to pose as another list member. In theory, it should be possible to keep the original signature after decryption. easy /wish Merge the Stefan-specific stuff in README.GPG with my SSLS stuff. Get rid of the Stefan version in my patch version. See also -------- There are some alternative approaches on integrating PGP with Mailman: https://sourceforge.net/projects/mmreencrypt/ , dating from 2000-10. mailman.patch.645297.tar.gz, Mailman patch #645297 by Ben Laurie ( http://www.apache-ssl.org/ben.html ) , at http://sourceforge.net/tracker/index.php?func=detail&aid=645297&group_id=103&atid=300103 , dating from 2002-11 secure-list-10-212.patch.gz , the NAH6 secure list patch, patch #646989 at http://sourceforge.net/tracker/index.php?func=detail&aid=646989&group_id=103&atid=300103 , dating from 2002-12 ChangeLog --------- 200CURRENT Joost van Baal * REAME.GPG: lots of (wishlist) bugs added, assigned priorities. * Mailman/GPGUtils.py: fix fatal bug: global name 'result' is not defined. Triggered under some circumstances when decrypting fails. * Mailman/GPGUtils.py, Mailman/Handlers/GpgSMTPDirect.py: fixed copyright statements (taken from Stefan's mailman-2.1.5-gpg_2005-05-03.diff.gz) 2005-04-21 Joost van Baal * Mailman/Handlers/Moderate.py: Force settings of gpg_postings_allowed/gpg_post_sign were mixed: bugfix. * Mailman/Defaults.py.in: More strict defaults: No web archive: (DEFAULT_ARCHIVE), if archive defined, not public (DEFAULT_ARCHIVE_PRIVATE), don't archive in mbox format (ARCHIVE_TO_MBOX), show list of subscribers to admin only (DEFAULT_PRIVATE_ROSTER). * README.GPG: Stefan's todo list merged. 2005-04-18 Joost van Baal * Mailman/MailList.py, Mailman/versions.py, bin/update: gpg_secret_key and gpg_public_key are of type string, even if unset. Otherwise, config_list might choke: it tries to invoke splitlines() on these settings. * Mailman/Handlers/Moderate.py: behave more sane on strange messages: code robustness fix. * Mailman/Handlers/GpgDecrypt.py, Mailman/Handlers/Moderate.py: GpgDecrypt is merged with Moderate: we need to share data about valid signatures among these things; adapting the Message type for passing this data is too intrusive. * Mailman/Handlers/Moderate.py: no longer adds valid-signature info to body. * Mailman/mm_cfg.py.in: this file is no longer patched, all config patching (i.e. DELIVERY_MODULE = 'GpgSMTPDirect') is done in Defaults.py * Mailman/GPGUtils.py: decryptMessage now uses more stable status fd interface from gnupg. Now returns _all_ key_ids of signers. 2005-03-24 Joost van Baal * Mailman/GPGUtils.py, Mailman/Handlers/Moderate.py: more fixes in copyright blurbs. * README.GPG: warnings on gotcha's added. * Mailman/Handlers/Moderate.py: fixed bug in code (TypeError) which would show up if some members didn't supply their public key. 2005-03-22 Joost van Baal * Updated this README.GPG file: more pointers. * Mailman/GPGUtils.py: fixed verifyMessage (it was unusable.) * Mailman/Handlers/Moderate.py: new verifyMessage interface: we now deal with both inline signatures and detached signatures. 2005-03-21 Joost van Baal * Mailman/Handlers/Moderate.py: fix bug in handling of gpg_post_sign (it was unusable.) * bin/update: add gpg_post_sign. * Mailman/Handlers/GpgDecrypt.py: Fixed copyright blurb, after consulting Stefan. (Mailman/GPGUtils.py will get fixed eventually.) 2005-03-15 Joost van Baal * Mailman/Handlers/Moderate.py: fix syntax error and missing import. Oops. * Mailman/GPGUtils.py: make sure verifyMessage returns a sequence, make sure it's not waiting on stdin. Add --no-permission-warning to gpg options: typically, we have a group-writable GnuPG homedirectory since both the webserver and the Mailman user interface with us. * Mailman/versions.py: add gpg_post_sign to list attributes, in order to fix AttributeError 2005-03-14 17:01:10 +0100 Joost van Baal * Mailman/Defaults.py.in, Mailman/GPGUtils.py, Mailman/Gui/Privacy.py, Mailman/Handlers/Hold.py, Mailman/Handlers/Moderate.py, Mailman/MailList.py: first shot at adding signature-verification support as a moderation criterium. 2005-02-11 Stefan Schlott (mailman-2.1.5-gpg_2005-02-22.diff.gz) - hide the key ID in the "good signature" info of the list server in the case of "anonymous lists" - change "Message had a good signature" into something more useful (if detached signatures aren't possible) that's not so easy to spoof (Thanks, Nicolas!) - typo in the section about mailclients (Thanks, Sebastian!)