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)
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)
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")
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
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)
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
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)
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 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
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)
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)
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, ))
def _makeHeaders(self, headers_pairs): headers = Headers() for name, value in headers_pairs: headers.addRawHeader(name, value) return headers
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,))