예제 #1
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)
예제 #2
0
    def _processRequest(self):
        """
        Process the request by sending it to the relevant server.

        @return: the HTTP response.
        @rtype: L{Response}
        """
        ssl, host, port, _ignore_path = self.server.details()
        path = "/" + config.Servers.ConduitName

        headers = Headers()
        headers.setHeader("Host", utf8String(host + ":{}".format(port)))
        if self.streamType:
            # For attachments we put the base64-encoded JSON data into a header
            headers.setHeader("Content-Type", self.streamType)
            headers.addRawHeader("XPOD", base64.b64encode(self.data))
        else:
            headers.setHeader("Content-Type", MimeType("application", "json", params={"charset": "utf-8", }))
        headers.setHeader("User-Agent", "CalendarServer/{}".format(version))
        headers.addRawHeader(*self.server.secretHeader())

        from twisted.internet import reactor
        f = Factory()
        f.protocol = HTTPClientProtocol
        ep = GAIEndpoint(reactor, host, port, _configuredClientContextFactory() if ssl else None)
        proto = (yield ep.connect(f))

        request = ClientRequest("POST", path, headers, self.stream if self.stream is not None else self.data)

        if accountingEnabledForCategory("xPod"):
            self.loggedRequest = yield self.logRequest(request)

        response = (yield proto.submitRequest(request))

        returnValue(response)
예제 #3
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")
예제 #4
0
def _parseRequest(request):

    lines = request.splitlines(True)

    method, uri, _ignore_version = lines.pop(0).split()

    hdrs = []
    body = None
    for line in lines:
        if body is not None:
            body.append(line)
        elif line.strip() == "":
            body = []
        elif line[0] in (" ", "\t"):
            hdrs[-1] += line
        else:
            hdrs.append(line)

    headers = Headers()
    for hdr in hdrs:
        name, value = hdr.split(':', 1)
        headers.addRawHeader(name, value.strip())

    stream = "".join(body)

    return method, uri, headers, stream
예제 #5
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)
예제 #6
0
def _parseRequest(request):

    lines = request.splitlines(True)

    method, uri, _ignore_version = lines.pop(0).split()

    hdrs = []
    body = None
    for line in lines:
        if body is not None:
            body.append(line)
        elif line.strip() == "":
            body = []
        elif line[0] in (" ", "\t"):
            hdrs[-1] += line
        else:
            hdrs.append(line)

    headers = Headers()
    for hdr in hdrs:
        name, value = hdr.split(':', 1)
        headers.addRawHeader(name, value.strip())

    stream = MemoryStream("".join(body))

    return method, uri, headers, stream
예제 #7
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)
예제 #8
0
 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)
예제 #9
0
    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)
예제 #10
0
    def requestForPath(self, path, method='GET'):
        """
        Get a L{Request} with a L{FakeChanRequest} for a given path and method.
        """
        headers = Headers()
        headers.addRawHeader("Host", "localhost:8008")
        req = SimpleStoreRequest(self, method, path, headers)

        # 'process()' normally sets these.  Shame on web2, having so much
        # partially-initialized stuff floating around.
        req.remoteAddr = '127.0.0.1'
        req.chanRequest = FakeChanRequest()
        req.credentialFactories = {}
        return req
예제 #11
0
    def requestForPath(self, path, method='GET'):
        """
        Get a L{Request} with a L{FakeChanRequest} for a given path and method.
        """
        headers = Headers()
        headers.addRawHeader("Host", "localhost:8008")
        req = SimpleStoreRequest(self, method, path, headers)

        # 'process()' normally sets these.  Shame on web2, having so much
        # partially-initialized stuff floating around.
        req.remoteAddr = '127.0.0.1'
        req.chanRequest = FakeChanRequest()
        req.credentialFactories = {}
        return req
예제 #12
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)
예제 #13
0
    def _processRequest(self):
        """
        Process the request by sending it to the relevant server.

        @return: the HTTP response.
        @rtype: L{Response}
        """
        ssl, host, port, _ignore_path = self.server.details()
        path = "/" + config.Servers.ConduitName

        headers = Headers()
        headers.setHeader("Host", utf8String(host + ":{}".format(port)))
        if self.streamType:
            # For attachments we put the base64-encoded JSON data into a header
            headers.setHeader("Content-Type", self.streamType)
            headers.addRawHeader("XPOD", base64.b64encode(self.data))
        else:
            headers.setHeader(
                "Content-Type",
                MimeType("application", "json", params={
                    "charset": "utf-8",
                }))
        headers.setHeader("User-Agent", "CalendarServer/{}".format(version))
        headers.addRawHeader(*self.server.secretHeader())

        from twisted.internet import reactor
        f = Factory()
        f.protocol = HTTPClientProtocol
        ep = GAIEndpoint(
            reactor, host, port,
            _configuredClientContextFactory(host) if ssl else None)
        proto = (yield ep.connect(f))

        request = ClientRequest(
            "POST", path, headers,
            self.stream if self.stream is not None else self.data)

        if accountingEnabledForCategory("xPod"):
            self.loggedRequest = yield self.logRequest(request)

        response = (yield proto.submitRequest(request))

        returnValue(response)
예제 #14
0
    def test_bestAcceptType(self):

        data = (
            (
                "#1.1",
                ("Accept", "text/plain"),
                ["text/plain"],
                "text/plain",
            ),
            (
                "#1.2",
                ("Accept", "text/plain"),
                ["text/calendar"],
                None,
            ),
            (
                "#1.3",
                ("Accept", "text/*"),
                ["text/plain"],
                "text/plain",
            ),
            (
                "#1.4",
                ("Accept", "*/*"),
                ["text/plain"],
                "text/plain",
            ),
            (
                "#2.1",
                ("Accept", "text/plain"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#2.2",
                ("Accept", "text/plain"),
                [
                    "text/calendar",
                    "application/text",
                ],
                None,
            ),
            (
                "#2.3",
                ("Accept", "text/*"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#2.4",
                ("Accept", "*/*"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#2.5",
                ("Accept", "application/text"),
                [
                    "text/plain",
                    "application/text",
                ],
                "application/text",
            ),
            (
                "#2.6",
                ("Accept", "application/*"),
                [
                    "text/plain",
                    "application/text",
                ],
                "application/text",
            ),
            (
                "#3.1",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#3.2",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                [
                    "text/calendar",
                    "application/calendar",
                ],
                None,
            ),
            (
                "#3.3",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#3.4",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#3.5",
                ("Accept", "text/plain;q=0.3, application/text;q=0.5"),
                [
                    "text/plain",
                    "application/text",
                ],
                "application/text",
            ),
            (
                "#3.6",
                ("Accept", "text/plain;q=0.5, application/*;q=0.3"),
                [
                    "text/plain",
                    "application/text",
                ],
                "text/plain",
            ),
            (
                "#4.1",
                ("Accept",
                 "text/plain;q=0.5, application/text;q=0.2, text/*;q=0.3"),
                [
                    "text/calendar",
                    "application/text",
                ],
                "text/calendar",
            ),
            (
                "#5.1",
                None,
                [
                    "text/calendar",
                    "application/text",
                ],
                "text/calendar",
            ),
        )

        for title, hdr, allowedTypes, result in data:
            hdrs = Headers()
            if hdr:
                hdrs.addRawHeader(*hdr)
            check = bestAcceptType(hdrs.getHeader("accept"), allowedTypes)
            self.assertEqual(check, result, msg="Failed %s" % (title, ))
예제 #15
0
 def _makeHeaders(self, headers_pairs):
     headers = Headers()
     for name, value in headers_pairs:
         headers.addRawHeader(name, value)
     return headers
예제 #16
0
    def test_bestAcceptType(self):

        data = (
            ("#1.1", ("Accept", "text/plain"), ["text/plain"], "text/plain"),
            ("#1.2", ("Accept", "text/plain"), ["text/calendar"], None),
            ("#1.3", ("Accept", "text/*"), ["text/plain"], "text/plain"),
            ("#1.4", ("Accept", "*/*"), ["text/plain"], "text/plain"),
            ("#2.1", ("Accept", "text/plain"), ["text/plain", "application/text"], "text/plain"),
            ("#2.2", ("Accept", "text/plain"), ["text/calendar", "application/text"], None),
            ("#2.3", ("Accept", "text/*"), ["text/plain", "application/text"], "text/plain"),
            ("#2.4", ("Accept", "*/*"), ["text/plain", "application/text"], "text/plain"),
            ("#2.5", ("Accept", "application/text"), ["text/plain", "application/text"], "application/text"),
            ("#2.6", ("Accept", "application/*"), ["text/plain", "application/text"], "application/text"),
            (
                "#3.1",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                ["text/plain", "application/text"],
                "text/plain",
            ),
            (
                "#3.2",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                ["text/calendar", "application/calendar"],
                None,
            ),
            (
                "#3.3",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                ["text/plain", "application/text"],
                "text/plain",
            ),
            (
                "#3.4",
                ("Accept", "text/plain;q=0.5, application/text;q=0.3"),
                ["text/plain", "application/text"],
                "text/plain",
            ),
            (
                "#3.5",
                ("Accept", "text/plain;q=0.3, application/text;q=0.5"),
                ["text/plain", "application/text"],
                "application/text",
            ),
            (
                "#3.6",
                ("Accept", "text/plain;q=0.5, application/*;q=0.3"),
                ["text/plain", "application/text"],
                "text/plain",
            ),
            (
                "#4.1",
                ("Accept", "text/plain;q=0.5, application/text;q=0.2, text/*;q=0.3"),
                ["text/calendar", "application/text"],
                "text/calendar",
            ),
            ("#5.1", None, ["text/calendar", "application/text"], "text/calendar"),
        )

        for title, hdr, allowedTypes, result in data:
            hdrs = Headers()
            if hdr:
                hdrs.addRawHeader(*hdr)
            check = bestAcceptType(hdrs.getHeader("accept"), allowedTypes)
            self.assertEqual(check, result, msg="Failed %s" % (title,))