def test_dkim_signed_but_from_unverified_address(self): """Sent from trusted dkim address, but only the From address is known. The sender is a known, but unverified address. See https://bugs.launchpad.net/launchpad/+bug/925597 """ from_address = "*****@*****.**" sender_address = "*****@*****.**" person = self.factory.makePerson( email=from_address, name='dkimtest', displayname='DKIM Test') self.factory.makeEmail(sender_address, person, EmailAddressStatus.NEW) self.preload_dns_response() tweaked_message = self.makeMessageText( sender=sender_address, from_address="DKIM Test <*****@*****.**>") signed_message = self.fake_signing(tweaked_message) principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertEqual(principal.person.preferredemail.email, from_address) self.assertWeaklyAuthenticated(principal, signed_message) self.assertDkimLogContains( 'valid dkim signature, but not from an active email address')
def test_clearsigned_message(self): # The test keys belong to Sample Person. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') msg = self._get_clearsigned_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse(IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_dkim_valid(self): signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response() principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertStronglyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_detached_signature_message(self): # Test a detached correct signature. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') msg = self._get_detached_message_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse(IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_require_strong_email_authentication_and_signed(self): sender = getUtility(IPersonSet).getByEmail('*****@*****.**') sender.require_strong_email_authentication = True msg = self._get_clearsigned_for_person(sender) principal = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principal.person) self.assertFalse(IWeaklyAuthenticatedPrincipal.providedBy(principal))
def test_clearsigned_message(self): # The test keys belong to Sample Person. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') msg = self._get_clearsigned_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse( IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_dkim_garbage_pubkey(self): signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response('garbage') principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**') self.assertDkimLogContains('invalid format in _domainkey txt record')
def test_dkim_nxdomain(self): # If there's no DNS entry for the pubkey it should be handled # decently. signed_message = self.fake_signing(self.makeMessageText()) principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_dkim_message_unsigned(self): # This is a degenerate case: a message with no signature is # treated as weakly authenticated. # The library doesn't log anything if there's no header at all. principal = authenticateEmail( signed_message_from_string(self.makeMessageText())) self.assertWeaklyAuthenticated(principal, self.makeMessageText()) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_clearsigned_message_wrong_sender(self): # If the message is signed, but the key doesn't belong to the sender, # the principle is set to the sender, but weakly authenticated. sender = self.factory.makePerson() msg = self._get_clearsigned_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertTrue(IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_detached_signature_message(self): # Test a detached correct signature. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') msg = self._get_detached_message_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse( IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_clearsigned_message_wrong_sender(self): # If the message is signed, but the key doesn't belong to the sender, # the principle is set to the sender, but weakly authenticated. sender = self.factory.makePerson() msg = self._get_clearsigned_for_person(sender) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertTrue( IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_unsigned_message(self): # An unsigned message will not have a signature nor signed content, # and generates a weakly authenticated principle. sender = self.factory.makePerson() email_message = self.factory.makeEmailMessage(sender=sender) msg = signed_message_from_string(email_message.as_string()) self.assertIs(None, msg.signedContent) self.assertIs(None, msg.signature) principle = authenticateEmail(msg) self.assertEqual(sender, principle.person) self.assertTrue(IWeaklyAuthenticatedPrincipal.providedBy(principle)) self.assertIs(None, msg.signature)
def test_trailing_whitespace(self): # Trailing whitespace should be ignored when verifying a message's # signature. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') body = ('A message with trailing spaces. \n' 'And tabs\t\t\n' 'Also mixed. \t ') msg = self._get_clearsigned_for_person(sender, body) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse(IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_dkim_body_mismatch(self): # The message has a syntactically valid DKIM signature that # doesn't actually correspond to what was signed. We log # something about this but we don't want to drop the message. signed_message = self.fake_signing(self.makeMessageText()) signed_message += 'blah blah' self.preload_dns_response() principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**') self.assertDkimLogContains('body hash mismatch')
def test_dkim_changed_from_realname(self): # If the real name part of the message has changed, it's detected. signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response() fiddled_message = signed_message.replace( 'From: Foo Bar <*****@*****.**>', 'From: Evil Foo <*****@*****.**>') principal = authenticateEmail( signed_message_from_string(fiddled_message)) # We don't care about the real name for determining the principal. self.assertWeaklyAuthenticated(principal, fiddled_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_unsigned_message(self): # An unsigned message will not have a signature nor signed content, # and generates a weakly authenticated principle. sender = self.factory.makePerson() email_message = self.factory.makeEmailMessage(sender=sender) msg = signed_message_from_string(email_message.as_string()) self.assertIs(None, msg.signedContent) self.assertIs(None, msg.signature) principle = authenticateEmail(msg) self.assertEqual(sender, principle.person) self.assertTrue( IWeaklyAuthenticatedPrincipal.providedBy(principle)) self.assertIs(None, msg.signature)
def test_trailing_whitespace(self): # Trailing whitespace should be ignored when verifying a message's # signature. sender = getUtility(IPersonSet).getByEmail('*****@*****.**') body = ( 'A message with trailing spaces. \n' 'And tabs\t\t\n' 'Also mixed. \t ') msg = self._get_clearsigned_for_person(sender, body) principle = authenticateEmail(msg) self.assertIsNot(None, msg.signature) self.assertEqual(sender, principle.person) self.assertFalse( IWeaklyAuthenticatedPrincipal.providedBy(principle))
def test_dkim_broken_pubkey(self): """Handle a subtly-broken pubkey like qq.com, see bug 881237. The message is not trusted but inbound message processing does not abort either. """ signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response('broken') principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**') self.assertDkimLogContains('unexpected error in DKIM verification')
def test_dkim_signing_irrelevant(self): # It's totally valid for a message to be signed by a domain other than # that of the From-sender, if that domain is relaying the message. # However, we shouldn't then trust the purported sender, because they # might have just made it up rather than relayed it. tweaked_message = self.makeMessageText( from_address='*****@*****.**') signed_message = self.fake_signing(tweaked_message) self.preload_dns_response() principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) # should come from From, not the dkim signature self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_dkim_changed_from_address(self): # If the address part of the message has changed, it's detected. # We still treat this as weakly authenticated by the purported # From-header sender, though perhaps in future we would prefer # to reject these messages. signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response() fiddled_message = signed_message.replace( 'From: Foo Bar <*****@*****.**>', 'From: Carlos <*****@*****.**>') principal = authenticateEmail( signed_message_from_string(fiddled_message)) self.assertWeaklyAuthenticated(principal, fiddled_message) # should come from From, not the dkim signature self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_dkim_untrusted_signer(self): # Valid signature from an untrusted domain -> untrusted signed_message = self.fake_signing(self.makeMessageText()) self.preload_dns_response() saved_domains = incoming._trusted_dkim_domains[:] def restore(): incoming._trusted_dkim_domains = saved_domains self.addCleanup(restore) incoming._trusted_dkim_domains = [] principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertWeaklyAuthenticated(principal, signed_message) self.assertEqual(principal.person.preferredemail.email, '*****@*****.**')
def test_dkim_signed_by_other_address(self): # If the message is From one of a person's addresses, and the Sender # corresponds to another, and there is a DKIM signature for the Sender # domain, this is valid - see bug 643223. For this to be a worthwhile # test we need the two addresses to be in different domains. It # will be signed by canonical.com, so make that the sender. person = self.factory.makePerson( email='*****@*****.**', name='dkimtest', displayname='DKIM Test') self.factory.makeEmail( person=person, address='*****@*****.**') self.preload_dns_response() tweaked_message = self.makeMessageText( sender="*****@*****.**", from_address="DKIM Test <*****@*****.**>") signed_message = self.fake_signing(tweaked_message) principal = authenticateEmail( signed_message_from_string(signed_message)) self.assertStronglyAuthenticated(principal, signed_message)
def test_unknown_email(self): # An unknown email address returns no principal. unknown = "*****@*****.**" mail = self.factory.makeSignedMessage(email_address=unknown) self.assertThat(authenticateEmail(mail), Is(None))
def test_badly_formed_email(self): # A badly formed email address returns no principal. bad = "\[email protected]" mail = self.factory.makeSignedMessage(email_address=bad) self.assertThat(authenticateEmail(mail), Is(None))
def test_unknown_email(self): # An unknown email address returns no principal. unknown = '*****@*****.**' mail = self.factory.makeSignedMessage(email_address=unknown) self.assertThat(authenticateEmail(mail), Is(None))
def test_badly_formed_email(self): # A badly formed email address returns no principal. bad = '\[email protected]' mail = self.factory.makeSignedMessage(email_address=bad) self.assertThat(authenticateEmail(mail), Is(None))