Exemple #1
0
        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")
Exemple #2
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)
    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"))
Exemple #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)
    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)
Exemple #6
0
def _doVerify(options):
    # Parse the HTTP file
    verify = open(os.path.expanduser(options["verify"])).read()
    _method, _uri, headers, body = _parseRequest(verify)

    # Check for local public key
    if options["pub-key"]:
        PublicKeyLookup_File.pubkeyfile = os.path.expanduser(options["pub-key"])
        lookup = (PublicKeyLookup_File,)
    else:
        lookup = None

    dkim = DKIMVerifier(headers, body, lookup)
    if options["fake-time"]:
        dkim.time = 0

    try:
        yield dkim.verify()
    except DKIMVerificationError, e:
        print("Verification Failed: %s" % (e,))
Exemple #7
0
def _doVerify(options):
    # Parse the HTTP file
    verify = open(options["verify"]).read()
    method, uri, headers, stream = _parseRequest(verify)

    request = ClientRequest(method, uri, headers, stream)

    # Check for local public key
    if options["pub-key"]:
        PublicKeyLookup_File.pubkeyfile = options["pub-key"]
        lookup = (PublicKeyLookup_File,)
    else:
        lookup = None

    dkim = DKIMVerifier(request, lookup)
    if options["fake-time"]:
        dkim.time = 0

    try:
        yield dkim.verify()
    except DKIMVerificationError, e:
        print("Verification Failed: %s" % (e,))
Exemple #8
0
def _doVerify(options):
    # Parse the HTTP file
    verify = open(options["verify"]).read()
    method, uri, headers, stream = _parseRequest(verify)

    request = ClientRequest(method, uri, headers, stream)

    # Check for local public key
    if options["pub-key"]:
        PublicKeyLookup_File.pubkeyfile = options["pub-key"]
        lookup = (PublicKeyLookup_File, )
    else:
        lookup = None

    dkim = DKIMVerifier(request, lookup)
    if options["fake-time"]:
        dkim.time = 0

    try:
        yield dkim.verify()
    except DKIMVerificationError, e:
        print("Verification Failed: %s" % (e, ))
Exemple #9
0
    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)
Exemple #10
0
    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"))