diff options
| author | J08nY | 2017-08-23 23:18:52 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-23 23:18:52 +0200 |
| commit | 5bfab2f9780f41d5ab061a2d3b338ae0f45e10cf (patch) | |
| tree | 8e347edc1156290b89df312eb279dc0133a2523d | |
| parent | 77c2dc1feed19224e1884250341873b88444a041 (diff) | |
| parent | 024a2481dfe320b7e4604d8e3088d6b88dab7325 (diff) | |
| download | mailman-pgp-5bfab2f9780f41d5ab061a2d3b338ae0f45e10cf.tar.gz mailman-pgp-5bfab2f9780f41d5ab061a2d3b338ae0f45e10cf.tar.zst mailman-pgp-5bfab2f9780f41d5ab061a2d3b338ae0f45e10cf.zip | |
| -rw-r--r-- | src/mailman_pgp/handlers/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman_pgp/handlers/signature_strip.py | 39 | ||||
| -rw-r--r-- | src/mailman_pgp/handlers/tests/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman_pgp/handlers/tests/test_signature_strip.py | 96 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/inline.py | 10 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/mime.py | 11 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/mime_multisig.py | 3 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/wrapper.py | 15 | ||||
| -rw-r--r-- | src/mailman_pgp/pipelines/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman_pgp/pipelines/default.py | 50 | ||||
| -rw-r--r-- | src/mailman_pgp/pipelines/tests/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman_pgp/pipelines/tests/test_default.py | 34 |
12 files changed, 258 insertions, 0 deletions
diff --git a/src/mailman_pgp/handlers/__init__.py b/src/mailman_pgp/handlers/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/mailman_pgp/handlers/__init__.py diff --git a/src/mailman_pgp/handlers/signature_strip.py b/src/mailman_pgp/handlers/signature_strip.py new file mode 100644 index 0000000..358a506 --- /dev/null +++ b/src/mailman_pgp/handlers/signature_strip.py @@ -0,0 +1,39 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +"""""" + +from mailman.interfaces.handler import IHandler +from public import public +from zope.interface import implementer + +from mailman_pgp.model.list import PGPMailingList +from mailman_pgp.pgp.wrapper import PGPWrapper + + +@public +@implementer(IHandler) +class SignatureStrip: + name = 'pgp-signature-strip' + description = 'Strip the signature of the message.' + + def process(self, mlist, msg, msgdata): + """See `IHandler`.""" + pgp_list = PGPMailingList.for_list(mlist) + if not pgp_list or not pgp_list.strip_original_sig: + return + + PGPWrapper(msg).strip_signature() diff --git a/src/mailman_pgp/handlers/tests/__init__.py b/src/mailman_pgp/handlers/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/mailman_pgp/handlers/tests/__init__.py diff --git a/src/mailman_pgp/handlers/tests/test_signature_strip.py b/src/mailman_pgp/handlers/tests/test_signature_strip.py new file mode 100644 index 0000000..b88c003 --- /dev/null +++ b/src/mailman_pgp/handlers/tests/test_signature_strip.py @@ -0,0 +1,96 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. +import unittest +from copy import deepcopy + +from mailman.app.lifecycle import create_list +from mailman.interfaces.usermanager import IUserManager +from zope.component import getUtility + +from mailman_pgp.config import mm_config +from mailman_pgp.database import mm_transaction, transaction +from mailman_pgp.handlers.signature_strip import SignatureStrip +from mailman_pgp.model.address import PGPAddress +from mailman_pgp.model.list import PGPMailingList +from mailman_pgp.pgp.inline import InlineWrapper +from mailman_pgp.pgp.mime import MIMEWrapper +from mailman_pgp.testing.layers import PGPConfigLayer +from mailman_pgp.testing.pgp import load_key, load_message + + +class TestSignatureStripHandler(unittest.TestCase): + layer = PGPConfigLayer + + def setUp(self): + self.handler = SignatureStrip() + + user_manager = getUtility(IUserManager) + with mm_transaction(): + self.mlist = create_list('test@example.com', + style_name='pgp-default') + self.sender = user_manager.create_address('anne@example.com') + + self.pgp_list = PGPMailingList.for_list(self.mlist) + with transaction(): + self.pgp_list.strip_original_sig = True + + self.sender_key = load_key('rsa_1024.priv.asc') + with transaction() as t: + self.pgp_sender = PGPAddress(self.sender) + self.pgp_sender.key = self.sender_key.pubkey + self.pgp_sender.key_confirmed = True + t.add(self.pgp_sender) + + self.msg_clear = load_message('clear.eml') + self.msg_inline_signed = load_message('inline_signed.eml') + self.msg_mime_signed = load_message('mime_signed.eml') + self.msg_inline_signed_invalid = load_message( + 'inline_cleartext_signed_invalid.eml') + self.msg_mime_signed_invalid = load_message( + 'mime_signed_invalid.eml') + + def test_has_handler(self): + self.assertIn(SignatureStrip.name, mm_config.handlers.keys()) + + def test_no_list(self): + with mm_transaction(): + ordinary = create_list('ordinary@example.com') + + self.handler.process(ordinary, self.msg_clear, {}) + + def test_no_strip(self): + with transaction(): + self.pgp_list.strip_original_sig = False + + msg = deepcopy(self.msg_mime_signed) + self.handler.process(self.mlist, msg, {}) + self.assertTrue(MIMEWrapper(msg).is_signed()) + + msg = deepcopy(self.msg_inline_signed) + self.handler.process(self.mlist, msg, {}) + self.assertTrue(InlineWrapper(msg).is_signed()) + + def test_strip(self): + msg = deepcopy(self.msg_mime_signed) + self.handler.process(self.mlist, msg, {}) + self.assertFalse(MIMEWrapper(msg).is_signed()) + self.assertFalse(MIMEWrapper(msg).has_signature()) + + msg = deepcopy(self.msg_inline_signed) + self.handler.process(self.mlist, msg, {}) + self.assertFalse(InlineWrapper(msg).is_signed()) + self.assertFalse(InlineWrapper(msg).has_signature()) diff --git a/src/mailman_pgp/pgp/inline.py b/src/mailman_pgp/pgp/inline.py index 410078c..24809d2 100644 --- a/src/mailman_pgp/pgp/inline.py +++ b/src/mailman_pgp/pgp/inline.py @@ -95,6 +95,16 @@ class InlineWrapper(BaseWrapper): continue yield msg + def strip_signature(self): + for part in walk(self.msg): + if not part.is_multipart() and self._is_signed(part): + try: + msg = PGPMessage.from_blob(part.get_payload()) + except: + continue + part.set_payload(msg.message) + return self + def _is_encrypted(self, part): try: msg = PGPMessage.from_blob(part.get_payload()) diff --git a/src/mailman_pgp/pgp/mime.py b/src/mailman_pgp/pgp/mime.py index 9ea6384..47e1037 100644 --- a/src/mailman_pgp/pgp/mime.py +++ b/src/mailman_pgp/pgp/mime.py @@ -103,6 +103,17 @@ class MIMEWrapper(BaseWrapper): return yield sig + def strip_signature(self): + """ + + :return: + :rtype: MIMEWrapper + """ + inner = self.msg.get_payload(0) + copy_headers(inner, self.msg, True) + self.msg.set_payload(inner.get_payload()) + return self + def is_encrypted(self): """ Whether the whole message is MIME encrypted as per RFC3156 section 4. diff --git a/src/mailman_pgp/pgp/mime_multisig.py b/src/mailman_pgp/pgp/mime_multisig.py index fb06cad..88886c0 100644 --- a/src/mailman_pgp/pgp/mime_multisig.py +++ b/src/mailman_pgp/pgp/mime_multisig.py @@ -74,6 +74,9 @@ class MIMEMultiSigWrapper(MIMEWrapper): continue yield sig + def strip_signature(self): + pass + def sign(self, key, **kwargs): """ Sign a message with key. diff --git a/src/mailman_pgp/pgp/wrapper.py b/src/mailman_pgp/pgp/wrapper.py index f746229..fdb7eeb 100644 --- a/src/mailman_pgp/pgp/wrapper.py +++ b/src/mailman_pgp/pgp/wrapper.py @@ -112,6 +112,21 @@ class PGPWrapper(BaseWrapper): elif self.inline.is_signed(): yield from self.inline.get_signature() + def strip_signature(self): + """ + + :return: + :rtype: PGPWrapper + """ + result = None + if self.mime.is_signed(): + result = self.mime.strip_signature() + elif self.multisig.is_signed(): + result = self.multisig.strip_signature() + elif self.inline.is_signed(): + result = self.inline.strip_signature() + return self._rewrap(result) + def sign(self, key, **kwargs): """ Sign a message with key. diff --git a/src/mailman_pgp/pipelines/__init__.py b/src/mailman_pgp/pipelines/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/mailman_pgp/pipelines/__init__.py diff --git a/src/mailman_pgp/pipelines/default.py b/src/mailman_pgp/pipelines/default.py new file mode 100644 index 0000000..e24ff05 --- /dev/null +++ b/src/mailman_pgp/pipelines/default.py @@ -0,0 +1,50 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. + +"""""" +from mailman.pipelines.base import BasePipeline + +from public import public + + +@public +class PGPPostingPipeline(BasePipeline): + """The built-in owner pipeline.""" + + name = 'pgp-posting-pipeline' + description = 'PGP posting pipeline' + + _default_handlers = ( + 'pgp-signature-strip', + 'mime-delete', + 'tagger', + 'member-recipients', + 'avoid-duplicates', + 'cleanse', + 'cleanse-dkim', + 'cook-headers', + 'subject-prefix', + 'rfc-2369', + 'to-archive', + 'to-digest', + 'to-usenet', + 'after-delivery', + 'acknowledge', + 'decorate', + 'dmarc', + 'to-outgoing', + ) diff --git a/src/mailman_pgp/pipelines/tests/__init__.py b/src/mailman_pgp/pipelines/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/mailman_pgp/pipelines/tests/__init__.py diff --git a/src/mailman_pgp/pipelines/tests/test_default.py b/src/mailman_pgp/pipelines/tests/test_default.py new file mode 100644 index 0000000..5bb54ce --- /dev/null +++ b/src/mailman_pgp/pipelines/tests/test_default.py @@ -0,0 +1,34 @@ +# Copyright (C) 2017 Jan Jancar +# +# This file is a part of the Mailman PGP plugin. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see <http://www.gnu.org/licenses/>. + +import unittest + +from mailman_pgp.config import mm_config +from mailman_pgp.handlers.signature_strip import SignatureStrip +from mailman_pgp.pipelines.default import PGPPostingPipeline +from mailman_pgp.testing.layers import PGPConfigLayer + + +class TestPGPPostingPipeline(unittest.TestCase): + layer = PGPConfigLayer + + def test_has_pipeline(self): + self.assertIn(PGPPostingPipeline.name, mm_config.pipelines.keys()) + + def test_has_handler(self): + pipeline = PGPPostingPipeline() + self.assertEqual(SignatureStrip, type(next(iter(pipeline)))) |
