Exemplo n.º 1
0
    def test_generateSignature(self):

        data = "Hello World!"

        for algorithm, hash_method in (
            ("rsa-sha1", hashlib.sha1,),
            ("rsa-sha256", hashlib.sha256,),
        ):
            stream = MemoryStream(data)
            headers = Headers()
            headers.addRawHeader("Originator", "mailto:[email protected]")
            headers.addRawHeader("Recipient", "mailto:[email protected]")
            headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"}))
            request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600)

            # Manually create what should be the correct thing to sign
            bodyhash = base64.b64encode(hash_method(data).digest())
            sign_this = """originator:mailto:[email protected]
recipient:mailto:[email protected]
content-type:%s
ischedule-version:1.0
dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=%s; b=""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], str(int(time.time())), str(int(time.time() + 3600)), algorithm, bodyhash)

            result = request.generateSignature(sign_this)

            key = RSA.importKey(open(self.private_keyfile).read())
            signature = DKIMUtils.sign(sign_this, key, DKIMUtils.hash_func(algorithm))

            self.assertEqual(result, signature)
Exemplo n.º 2
0
    def test_sign(self):

        data = "Hello World!"
        for algorithm, hash_method in (
            ("rsa-sha1", hashlib.sha1,),
            ("rsa-sha256", hashlib.sha256,),
        ):
            stream = MemoryStream(data)
            headers = Headers()
            headers.addRawHeader("Originator", "mailto:[email protected]")
            headers.addRawHeader("Recipient", "mailto:[email protected]")
            headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"}))
            request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600)
            result = (yield request.sign())

            # Manually create what should be the correct thing to sign and make sure signatures match
            bodyhash = base64.b64encode(hash_method(DKIMUtils.canonicalizeBody(data)).digest())
            sign_this = """originator:mailto:[email protected]
recipient:mailto:[email protected]
content-type:%s
ischedule-version:1.0
ischedule-message-id:%s
dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=private-exchange:http/well-known:dns/txt; c=ischedule-relaxed/simple; h=Originator:Recipient:Content-Type:iSchedule-Version:iSchedule-Message-ID; bh=%s; b=""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], request.message_id, request.time, request.expire, algorithm, bodyhash)
            key = RSA.importKey(open(self.private_keyfile).read())
            signature = DKIMUtils.sign(sign_this, key, DKIMUtils.hash_func(algorithm))

            self.assertEqual(result, signature)

            # Make sure header is updated in the request
            updated_header = "v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=private-exchange:http/well-known:dns/txt; c=ischedule-relaxed/simple; h=Originator:Recipient:Content-Type:iSchedule-Version:iSchedule-Message-ID; bh=%s; b=%s" % (request.time, request.expire, algorithm, bodyhash, signature,)
            self.assertEqual(request.headers.getRawHeaders("DKIM-Signature")[0], updated_header)

            # Try to verify result using public key
            pubkey = RSA.importKey(open(self.public_keyfile).read())
            self.assertEqual(DKIMUtils.verify(sign_this, result, pubkey, DKIMUtils.hash_func(algorithm)), None)
Exemplo n.º 3
0
    def test_cached_key(self):

        # Create cache entry
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(
            DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [
            DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data, ))
        ]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Cache valid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(
            DKIMUtils.extractTags(dkim))
        lookup.keys = []
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Cache invalid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(
            DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = []
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)
Exemplo n.º 4
0
    def test_locate_public_key(self):
        """
        L{DKIMVerifier.locatePublicKey} correctly finds key matching headers.
        """

        data = (
            # Valid
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
                True,
            ),
            # Invalid - no method
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
                False,
            ),
            # Invalid - wrong algorithm
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; h=sha-1; p=%s" % (self.public_key_data,))],
                False,
            ),
        )

        for hdrs, keys, result in data:
            headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
            TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys
            TestPublicKeyLookup.PublicKeyLookup_Testing.flushCache()
            verifier = DKIMVerifier(self._makeHeaders(headers), "", key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,))
            verifier.processDKIMHeader()
            pkey = (yield verifier.locatePublicKey())
            if result:
                self.assertTrue(pkey is not None)
            else:
                self.assertTrue(pkey is None)
Exemplo n.º 5
0
    def test_locate_public_key(self):
        """
        L{DKIMVerifier.locatePublicKey} correctly finds key matching headers.
        """

        data = (
            # Valid
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
                True,
            ),
            # Invalid - no method
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
                False,
            ),
            # Invalid - wrong algorithm
            (
                """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
                [DKIMUtils.extractTags("v=DKIM1; h=sha-1; p=%s" % (self.public_key_data,))],
                False,
            ),
        )

        for hdrs, keys, result in data:
            headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
            TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys
            TestPublicKeyLookup.PublicKeyLookup_Testing.flushCache()
            verifier = DKIMVerifier(self._makeHeaders(headers), "", key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,))
            verifier.processDKIMHeader()
            pkey = (yield verifier.locatePublicKey())
            if result:
                self.assertTrue(pkey is not None)
            else:
                self.assertTrue(pkey is None)
Exemplo n.º 6
0
    def test_canonicalize_body(self):
        """
        L{DKIMUtils.canonicalizeBody} correctly canonicalizes bodies.
        """

        data = (
            (
                """Simple""",
                """Simple\n""",
            ),
            (
                """Simple\n""",
                """Simple\n""",
            ),
            (
                """Simple\n\n""",
                """Simple\n""",
            ),
        )

        for text, result in data:
            self.assertEqual(
                DKIMUtils.canonicalizeBody(text.replace("\n", "\r\n")),
                result.replace("\n", "\r\n"),
            )
Exemplo n.º 7
0
    def test_canonicalize_body(self):
        """
        L{DKIMUtils.canonicalizeBody} correctly canonicalizes bodies.
        """

        data = (
            (
                """Simple""",
                """Simple\n""",
            ),
            (
                """Simple\n""",
                """Simple\n""",
            ),
            (
                """Simple\n\n""",
                """Simple\n""",
            ),
        )

        for text, result in data:
            self.assertEqual(
                DKIMUtils.canonicalizeBody(text.replace("\n", "\r\n")),
                result.replace("\n", "\r\n"),
            )
Exemplo n.º 8
0
    def test_body_hash(self):

        data = "Hello World!"
        for algorithm, hash_method in (
            (
                "rsa-sha1",
                hashlib.sha1,
            ),
            (
                "rsa-sha256",
                hashlib.sha256,
            ),
        ):
            stream = str(data)
            headers = Headers()
            headers.addRawHeader("Originator", "mailto:[email protected]")
            headers.addRawHeader("Recipient", "mailto:[email protected]")
            headers.setHeader(
                "Content-Type",
                MimeType("text", "calendar", **{
                    "component": "VEVENT",
                    "charset": "utf-8"
                }))
            request = DKIMRequest("POST", "/", headers, stream, "example.com",
                                  "dkim", "/tmp/key", algorithm, (
                                      "Originator",
                                      "Recipient",
                                      "Content-Type",
                                  ), True, True, True, 3600)
            hash = base64.b64encode(
                hash_method(DKIMUtils.canonicalizeBody(data)).digest())
            result = (yield request.bodyHash())
            self.assertEqual(result, hash)
Exemplo n.º 9
0
    def test_HTTP_URI_key(self):

        # Need to setup a fake resolver
        module = getModule(__name__)
        dataPath = module.filePath.sibling("data")
        bindPath = dataPath.child("db.example.com")
        self.patch(config.Scheduling.iSchedule, "DNSDebug", bindPath.path)
        utils.DebugResolver = None
        utils._initResolver()

        for d, s, result in (
            ("example.com", "_ischedule",
             "https://key.example.com:8443/.well-known/domainkey/example.com/_ischedule"
             ),
            ("www.example.com", "_ischedule",
             "http://key.example.com/.well-known/domainkey/www.example.com/_ischedule"
             ),
            ("example.org", "_ischedule",
             "https://example.org/.well-known/domainkey/example.org/_ischedule"
             ),
        ):
            dkim = "v=1; d=%s; s = %s; t = 1234; a=rsa-sha1; q=http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=" % (
                d,
                s,
            )
            tester = PublicKeyLookup_HTTP_WellKnown(
                DKIMUtils.extractTags(dkim))
            uri = (yield tester._getURI())
            self.assertEqual(uri, result)
Exemplo n.º 10
0
    def test_canonicalize_header(self):
        """
        L{DKIMVerifier.canonicalizeHeader} correctly canonicalizes headers.
        """

        data = (
            ("Content-Type", " text/calendar  ; charset =  \"utf-8\"  ", "content-type:text/calendar ; charset = \"utf-8\"\r\n"),
            ("Originator", "  mailto:[email protected]  ", "originator:mailto:[email protected]\r\n"),
            ("Recipient", "  mailto:[email protected]  ,\t mailto:[email protected]\t\t  ", "recipient:mailto:[email protected],mailto:[email protected]\r\n"),
            ("iSchedule-Version", " 1.0 ", "ischedule-version:1.0\r\n"),
            (
                "DKIM-Signature",
                "  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a b  c; b=d ef",
                "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a b c; b=",
            ),
            (
                "DKIM-Signature",
                "  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; b= def ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a\t bc",
                "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; b= ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a bc",
            ),
        )

        for name, value, result in data:
            verifier = DKIMVerifier(self._makeHeaders(((name, value,),)), "")
            if name == "DKIM-Signature":
                verifier.processDKIMHeader()
            canonicalized = DKIMUtils.canonicalizeHeader(name, value, verifier.dkim_tags if name == "DKIM-Signature" else None)
            self.assertEqual(canonicalized, result)
Exemplo n.º 11
0
    def test_private_exchange(self):

        keydir = self.mktemp()
        PublicKeyLookup_PrivateExchange.directory = keydir
        os.mkdir(keydir)
        keyfile = os.path.join(keydir, "example.com#dkim")
        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; p=%s
""" % (self.public_key_data, ))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        dkim = "v=1; d=example.com; s = dkim2; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; s=email; p=%s
""" % (self.public_key_data, ))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; s=email; p=%s
v=DKIM1; s=ischedule; p=%s
""" % (
                self.public_key_data,
                self.public_key_data,
            ))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)
Exemplo n.º 12
0
    def test_private_exchange(self):

        keydir = self.mktemp()
        PublicKeyLookup_PrivateExchange.directory = keydir
        os.mkdir(keydir)
        keyfile = os.path.join(keydir, "example.com#dkim")
        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; p=%s
""" % (self.public_key_data,))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        dkim = "v=1; d=example.com; s = dkim2; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; s=email; p=%s
""" % (self.public_key_data,))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        with open(keyfile, "w") as f:
            f.write("""v=DKIM1; s=email; p=%s
v=DKIM1; s=ischedule; p=%s
""" % (self.public_key_data, self.public_key_data,))

        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = PublicKeyLookup_PrivateExchange(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)
Exemplo n.º 13
0
    def test_selector_key(self):

        for lookup, d, result in (
            (PublicKeyLookup_DNSTXT, "example.com", "dkim._domainkey.example.com"),
            (PublicKeyLookup_DNSTXT, "calendar.example.com", "dkim._domainkey.calendar.example.com"),
            (PublicKeyLookup_HTTP_WellKnown, "example.com", "https://example.com/.well-known/domainkey/example.com/dkim"),
            (PublicKeyLookup_HTTP_WellKnown, "calendar.example.com", "https://example.com/.well-known/domainkey/calendar.example.com/dkim"),
            (PublicKeyLookup_PrivateExchange, "example.com", "example.com#dkim"),
            (PublicKeyLookup_PrivateExchange, "calendar.example.com", "calendar.example.com#dkim"),
        ):
            dkim = "v=1; d=%s; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=" % (d,)
            tester = lookup(DKIMUtils.extractTags(dkim))
            self.assertEqual(tester._getSelectorKey(), result)
Exemplo n.º 14
0
    def test_cached_key(self):

        # Create cache entry
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Cache valid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.keys = []
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Cache invalid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = []
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)
Exemplo n.º 15
0
    def test_body_hash(self):

        data = "Hello World!"
        for algorithm, hash_method in (
            ("rsa-sha1", hashlib.sha1,),
            ("rsa-sha256", hashlib.sha256,),
        ):
            stream = str(data)
            headers = Headers()
            headers.addRawHeader("Originator", "mailto:[email protected]")
            headers.addRawHeader("Recipient", "mailto:[email protected]")
            headers.setHeader("Content-Type", MimeType("text", "calendar", **{"component": "VEVENT", "charset": "utf-8"}))
            request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", "/tmp/key", algorithm, ("Originator", "Recipient", "Content-Type",), True, True, True, 3600)
            hash = base64.b64encode(hash_method(DKIMUtils.canonicalizeBody(data)).digest())
            result = (yield request.bodyHash())
            self.assertEqual(result, hash)
Exemplo n.º 16
0
    def test_HTTP_URI_key(self):

        # Need to setup a fake resolver
        module = getModule(__name__)
        dataPath = module.filePath.sibling("data")
        bindPath = dataPath.child("db.example.com")
        self.patch(config.Scheduling.iSchedule, "DNSDebug", bindPath.path)
        utils.DebugResolver = None
        utils._initResolver()

        for d, s, result in (
            ("example.com", "_ischedule", "https://key.example.com:8443/.well-known/domainkey/example.com/_ischedule"),
            ("www.example.com", "_ischedule", "http://key.example.com/.well-known/domainkey/www.example.com/_ischedule"),
            ("example.org", "_ischedule", "https://example.org/.well-known/domainkey/example.org/_ischedule"),
        ):
            dkim = "v=1; d=%s; s = %s; t = 1234; a=rsa-sha1; q=http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=" % (d, s,)
            tester = PublicKeyLookup_HTTP_WellKnown(DKIMUtils.extractTags(dkim))
            uri = (yield tester._getURI())
            self.assertEqual(uri, result)
Exemplo n.º 17
0
    def test_TXT_key(self):

        # Need to setup a fake resolver
        module = getModule(__name__)
        dataPath = module.filePath.sibling("data")
        bindPath = dataPath.child("db.example.com")
        self.patch(config.Scheduling.iSchedule, "DNSDebug", bindPath.path)
        utils.DebugResolver = None
        utils._initResolver()

        for d, s, result in (
            ("example.com", "_ischedule", True),
            ("example.com", "_revoked", False),
            ("example.com", "dkim", False),
            ("calendar.example.com", "_ischedule", False),
            ("example.org", "_ischedule", False),
        ):
            dkim = "v=1; d=%s; s = %s; t = 1234; a=rsa-sha1; q=dns/txt ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=" % (d, s,)
            tester = PublicKeyLookup_DNSTXT(DKIMUtils.extractTags(dkim))
            pkey = yield tester.getPublicKey(False)
            self.assertEqual(pkey is not None, result)
Exemplo n.º 18
0
        root.putChild(config.Servers.ConduitName, conduit)

    #
    # iSchedule service (not used for podding)
    #
    if config.Scheduling.iSchedule.Enabled:
        log.info("Setting up iSchedule inbox resource: {cls}", cls=iScheduleResourceClass)

        ischedule = iScheduleResourceClass(
            root,
            newStore,
        )
        root.putChild("ischedule", ischedule)

        # Do DomainKey resources
        DKIMUtils.validConfiguration(config)
        if config.Scheduling.iSchedule.DKIM.Enabled:
            log.info("Setting up domainkey resource: {res}", res=DomainKeyResource)
            domain = config.Scheduling.iSchedule.DKIM.Domain if config.Scheduling.iSchedule.DKIM.Domain else config.ServerHostName
            dk = DomainKeyResource(
                domain,
                config.Scheduling.iSchedule.DKIM.KeySelector,
                config.Scheduling.iSchedule.DKIM.PublicKeyFile,
            )
            wellKnownResource.putChild("domainkey", dk)

    #
    # WebCal
    #
    if config.WebCalendarRoot:
        log.info("Setting up WebCalendar resource: {res}",
Exemplo n.º 19
0
        root.putChild(config.Servers.InboxName, ischedule)

    #
    # iSchedule service (not used for podding)
    #
    if config.Scheduling.iSchedule.Enabled:
        log.info("Setting up iSchedule inbox resource: {cls}", cls=iScheduleResourceClass)

        ischedule = iScheduleResourceClass(
            root,
            newStore,
        )
        root.putChild("ischedule", ischedule)

        # Do DomainKey resources
        DKIMUtils.validConfiguration(config)
        if config.Scheduling.iSchedule.DKIM.Enabled:
            log.info("Setting up domainkey resource: {res}", res=DomainKeyResource)
            domain = config.Scheduling.iSchedule.DKIM.Domain if config.Scheduling.iSchedule.DKIM.Domain else config.ServerHostName
            dk = DomainKeyResource(
                domain,
                config.Scheduling.iSchedule.DKIM.KeySelector,
                config.Scheduling.iSchedule.DKIM.PublicKeyFile,
            )
            wellKnownResource.putChild("domainkey", dk)

    #
    # WebCal
    #
    if config.WebCalendarRoot:
        log.info("Setting up WebCalendar resource: {res}",
Exemplo n.º 20
0
    def test_get_key(self):

        # Valid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Valid with more tags
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k = rsa ; h=  sha1 : sha256  ; s=ischedule ; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Invalid - key type
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=dsa ; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        # Invalid - hash
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; h=sha512 ; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        # Invalid - service
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p=%s" % (self.public_key_data,))]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        # Invalid - revoked
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p=")]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)

        # Multiple valid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [
            DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,)),
            DKIMUtils.extractTags("v=DKIM1; k = rsa ; h=  sha1 : sha256  ; s=ischedule ; p=%s" % (self.public_key_data,)),
            DKIMUtils.extractTags("v=DKIM1; k = rsa ; h=  sha1 : sha256  ; s=* ; p=%s" % (self.public_key_data,)),
        ]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Multiple - some valid, some invalid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [
            DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p="),
            DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,)),
            DKIMUtils.extractTags("v=DKIM1; k = rsa ; h=  sha1 : sha256  ; s=ischedule ; p=%s" % (self.public_key_data,)),
            DKIMUtils.extractTags("v=DKIM1; k = rsa ; h=  sha1 : sha256  ; s=* ; p=%s" % (self.public_key_data,)),
        ]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is not None)

        # Multiple - invalid
        dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known:private-exchange ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="
        lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
        lookup.flushCache()
        lookup.keys = [
            DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p="),
            DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p="),
        ]
        pubkey = (yield lookup.getPublicKey())
        self.assertTrue(pubkey is None)
Exemplo n.º 21
0
class TestDKIMVerifier (TestDKIMBase):
    """
    L{DKIMVerifier} support tests.
    """

    class StubRequest(object):

        def __init__(self, method, uri, headers, body):
            self.method = method
            self.uri = uri
            self.headers = Headers()
            for name, value in headers:
                self.headers.addRawHeader(name, value)
            self.stream = MemoryStream(body)


    def _makeHeaders(self, headers_pairs):
        headers = Headers()
        for name, value in headers_pairs:
            headers.addRawHeader(name, value)
        return headers


    def test_valid_dkim_headers(self):
        """
        L{DKIMVerifier.processDKIMHeader} correctly validates DKIM-Signature headers.
        """

        data = (
            # Bogus
            ((("DKIM-Signature", "v=1"),), False,),

            # More than one
            ((
                ("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),
                ("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha256; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),
            ), False,),

            # Valid
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),), True,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def"),), True,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; x=%d; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() + 30),)),), True,),

            # Invalid
            ((("DKIM-Signature", "v=2; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha512; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; c=ischedule-relaxed/relaxed; h=Originator:Recipient; bh=abc; b=def"),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; c=ischedule-relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; x=%d; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() - 30),)),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; x=%d; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() - 30),)),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; x=%d; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() - 30),)),), False,),
            ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; x=%d; a=rsa-sha256; q=dns/txt; c=ischedule-relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() - 30),)),), False,),
        )

        for headers, result in data:
            verifier = DKIMVerifier(self._makeHeaders(headers), "")
            if result:
                verifier.processDKIMHeader()
            else:
                self.assertRaises(DKIMVerificationError, verifier.processDKIMHeader)


    def test_canonicalize_header(self):
        """
        L{DKIMVerifier.canonicalizeHeader} correctly canonicalizes headers.
        """

        data = (
            ("Content-Type", " text/calendar  ; charset =  \"utf-8\"  ", "content-type:text/calendar ; charset = \"utf-8\"\r\n"),
            ("Originator", "  mailto:[email protected]  ", "originator:mailto:[email protected]\r\n"),
            ("Recipient", "  mailto:[email protected]  ,\t mailto:[email protected]\t\t  ", "recipient:mailto:[email protected],mailto:[email protected]\r\n"),
            ("iSchedule-Version", " 1.0 ", "ischedule-version:1.0\r\n"),
            (
                "DKIM-Signature",
                "  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a b  c; b=d ef",
                "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a b c; b=",
            ),
            (
                "DKIM-Signature",
                "  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; b= def ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a\t bc",
                "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; b= ; c=ischedule-relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=a bc",
            ),
        )

        for name, value, result in data:
            verifier = DKIMVerifier(self._makeHeaders(((name, value,),)), "")
            if name == "DKIM-Signature":
                verifier.processDKIMHeader()
            canonicalized = DKIMUtils.canonicalizeHeader(name, value, verifier.dkim_tags if name == "DKIM-Signature" else None)
            self.assertEqual(canonicalized, result)


    def test_extract_headers(self):
        """
        L{DKIMVerifier.extractSignedHeaders} correctly extracts canonicalizes headers.
        """

        data = (
            # Count on Recipient
            ("""Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
iSchedule-Version: 1.0
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
            """content-type:text/calendar ; charset = "utf-8"
originator:mailto:[email protected]
recipient:mailto:[email protected],mailto:[email protected]
ischedule-version:1.0
dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
            ),
            # Exact count on Recipient
            ("""Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Recipient:\t\t  mailto:[email protected]
iSchedule-Version: 1.0
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
            """content-type:text/calendar ; charset = "utf-8"
originator:mailto:[email protected]
recipient:mailto:[email protected],mailto:[email protected],mailto:[email protected]
ischedule-version:1.0
dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
            ),
            # Re-ordered Content-Type
            ("""Host:example.com
iSchedule-Version: 1.0
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Content-Type: text/calendar  ; charset =  "utf-8"
Cache-Control:no-cache
Connection:close
""",
            """content-type:text/calendar ; charset = "utf-8"
originator:mailto:[email protected]
recipient:mailto:[email protected],mailto:[email protected]
ischedule-version:1.0
dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
            ),
        )

        for hdrs, result in data:
            headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
            verifier = DKIMVerifier(self._makeHeaders(headers), "")
            verifier.processDKIMHeader()
            extracted = verifier.extractSignedHeaders()
            self.assertEqual(extracted, result.replace("\n", "\r\n"))


    def test_locate_public_key(self):
        """
        L{DKIMVerifier.locatePublicKey} correctly finds key matching headers.
        """

        data = (
            # Valid
            ("""Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            True,
            ),
            # Invalid - no method
            ("""Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            ),
            # Invalid - wrong algorithm
            ("""Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
DKIM-Signature:  v=1;\t\t d=example.com; s = dkim; t\t=\t1234; a=rsa-sha1; \t\tq=dns/txt:http/well-known\t\t; c=ischedule-relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Cache-Control:no-cache
Connection:close
""",
            [DKIMUtils.extractTags("v=DKIM1; h=sha-1; p=%s" % (self.public_key_data,))],
            False,
            ),
        )

        for hdrs, keys, result in data:
            headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
            TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys
            verifier = DKIMVerifier(self._makeHeaders(headers), "", key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,))
            verifier.processDKIMHeader()
            pkey = (yield verifier.locatePublicKey())
            if result:
                self.assertNotEqual(pkey, None)
            else:
                self.assertEqual(pkey, None)


    @inlineCallbacks
    def test_verify(self):
        """
        L{DKIMVerifier.verify} correctly finds key matching headers.
        """

        @inlineCallbacks
        def _verify(hdrs, body, keys, result, sign_headers=("Originator", "Recipient", "Content-Type",), manipulate_request=None):
            for algorithm in ("rsa-sha1", "rsa-sha256",):
                # Create signature
                stream = MemoryStream(body)
                headers = Headers()
                for name, value in [hdr.split(":", 1) for hdr in hdrs.splitlines()]:
                    headers.addRawHeader(name, value)
                request = DKIMRequest("POST", "/", headers, stream, "example.com", "dkim", self.private_keyfile, algorithm, sign_headers, True, True, True, 3600)
                yield request.sign()

                # Possibly munge the request after the signature is done
                if manipulate_request is not None:
                    manipulate_request(request)

                # Verify signature
                TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys
                data = (yield allDataFromStream(request.stream))
                verifier = DKIMVerifier(request.headers, data, key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,))
                TestPublicKeyLookup.PublicKeyLookup_Testing({}).flushCache()
                try:
                    yield verifier.verify()
                except Exception, e:
                    if result:
                        self.fail("DKIMVerifier:verify failed: %s" % (e,))
                else:
                    if not result:
                        self.fail("DKIMVerifier:verify did not fail")

        # Valid
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            True,
        )

        # Invalid - key revoked
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=")],
            False,
        )

        # Invalid - missing header
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            manipulate_request=lambda request: request.headers.removeHeader("Originator")
        )

        # Invalid - changed header
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            manipulate_request=lambda request: request.headers.setRawHeaders("Originator", ("mailto:[email protected]",))
        )

        # Invalid - changed body
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            manipulate_request=lambda request: setattr(request, "stream", MemoryStream("BEGIN:DATA\n")),
        )

        # Invalid - extra header
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            manipulate_request=lambda request: request.headers.getRawHeaders("Recipient").insert(0, "mailto:[email protected]"),
        )

        # Valid - header
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            True,
            sign_headers=("Originator", "Recipient", "Content-Type",),
        )

        # Invalid - over sign header extra header
        yield _verify(
            """Host:example.com
Content-Type: text/calendar  ; charset =  "utf-8"
Originator:  mailto:[email protected]
Recipient:  mailto:[email protected]  ,\t mailto:[email protected]\t\t
Cache-Control:no-cache
Connection:close
""",
            """BEGIN:DATA
END:DATA
""",
            [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
            False,
            sign_headers=("Originator", "Recipient", "Content-Type",),
            manipulate_request=lambda request: request.headers.addRawHeader("Recipient", ("mailto:[email protected]",))
        )