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 _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 _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 = MemoryStream("".join(body)) return method, uri, headers, stream
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 calendar_query(self, calendar_uri, query, got_xml, data, no_init): if not no_init: response = yield self.send( SimpleStoreRequest(self, "MKCALENDAR", calendar_uri, authPrincipal=self.authPrincipal)) response = IResponse(response) if response.code != responsecode.CREATED: self.fail("MKCALENDAR failed: %s" % (response.code, )) if data: for filename, icaldata in data.iteritems(): request = SimpleStoreRequest( self, "PUT", joinURL(calendar_uri, filename + ".ics"), headers=Headers({ "content-type": MimeType.fromString("text/calendar") }), authPrincipal=self.authPrincipal) request.stream = MemoryStream(icaldata) yield self.send(request) else: # Add holiday events to calendar for child in FilePath(self.holidays_dir).children(): if os.path.splitext(child.basename())[1] != ".ics": continue request = SimpleStoreRequest( self, "PUT", joinURL(calendar_uri, child.basename()), headers=Headers({ "content-type": MimeType.fromString("text/calendar") }), authPrincipal=self.authPrincipal) request.stream = MemoryStream(child.getContent()) yield self.send(request) request = SimpleStoreRequest(self, "REPORT", calendar_uri, authPrincipal=self.authPrincipal) request.stream = MemoryStream(query.toxml()) response = yield self.send(request) response = IResponse(response) if response.code != responsecode.MULTI_STATUS: self.fail("REPORT failed: %s" % (response.code, )) returnValue((yield davXMLFromStream(response.stream).addCallback(got_xml)))
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 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 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_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 test_givenURIsForKeys(self): expected_response = (200, Headers({}), "Foobarbaz") _key = ( 'PROPFIND', '/principals/__uids__/cdaboo/', '/calendars/users/cdaboo/', '1', hash('foobar'), ) expected_key = hashlib.md5(':'.join([str(t) for t in _key])).hexdigest() self.memcacheStub._cache[expected_key] = ( 0, # flags cPickle.dumps( ('principalToken0', StubDirectoryRecord('cdaboo').cacheToken(), 'uriToken0', { '/calendars/__uids__/cdaboo/calendars/': 'childToken0' }, (expected_response[0], dict(list(expected_response[1].getAllRawHeaders())), expected_response[2])))) d = self.rc.getResponseForRequest( StubRequest('PROPFIND', '/calendars/users/cdaboo/', '/principals/__uids__/cdaboo/')) d.addCallback(self.assertResponse, expected_response) return d
def __init__(self, method, uri, headers, stream): """ @param method: The HTTP method to for this request, ex: 'GET', 'HEAD', 'POST', etc. @type method: C{str} @param uri: The URI of the resource to request, this may be absolute or relative, however the interpretation of this URI is left up to the remote server. @type uri: C{str} @param headers: Headers to be sent to the server. It is important to note that this object does not create any implicit headers. So it is up to the HTTP Client to add required headers such as 'Host'. @type headers: C{dict}, L{txweb2.http_headers.Headers}, or C{None} @param stream: Content body to send to the remote HTTP server. @type stream: L{txweb2.stream.IByteStream} """ self.method = method self.uri = uri if isinstance(headers, Headers): self.headers = headers else: self.headers = Headers(headers or {}) if stream is not None: self.stream = IByteStream(stream) else: self.stream = None
def test_timeoutOnPUT(self): """ PUT gets a 503 on a lock timeout. """ # Create a fake lock txn = self.transactionUnderTest() yield NamedLock.acquire(txn, "ImplicitUIDLock:%s" % (hashlib.md5("uid1").hexdigest(),)) # PUT fails principal = yield self.actualRoot.findPrincipalForAuthID("wsanchez") request = SimpleStoreRequest( self, "PUT", "/calendars/users/wsanchez/calendar/1.ics", headers=Headers({"content-type": MimeType.fromString("text/calendar")}), authPrincipal=principal ) request.stream = MemoryStream("""BEGIN:VCALENDAR CALSCALE:GREGORIAN PRODID:-//Apple Computer\, Inc//iCal 2.0//EN VERSION:2.0 BEGIN:VEVENT UID:uid1 DTSTART;VALUE=DATE:20020101 DTEND;VALUE=DATE:20020102 DTSTAMP:20020101T121212Z SUMMARY:New Year's Day END:VEVENT END:VCALENDAR """.replace("\n", "\r\n")) response = yield self.send(request) self.assertEqual(response.code, responsecode.SERVICE_UNAVAILABLE)
def __init__(self, rootResource, method, path, uri='/', transaction=None): self.rootResource = rootResource self.method = method self.path = path self.uri = uri self._resourcesByURL = {} self._urlsByResource = {} self.headers = Headers() if transaction is not None: self._newStoreTransaction = transaction
def render(self, resource): headers = Headers() request = Request(chanRequest=None, command=None, path="/", version=None, contentLength=None, headers=headers) return resource.render(request)
def __init__(self, method, uri, authnUser, depth='1', body=None): self.method = method self.uri = uri self.authnUser = StubPrincipal(authnUser) self.headers = Headers({'depth': depth}) if body is None: body = "foobar" self.body = body self.stream = MemoryStream(body) self.site = StubSite()
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 setUp(self): super(MemcacheResponseCacheTests, self).setUp() memcacheStub = InMemoryMemcacheProtocol() self.rc = MemcacheResponseCache(None, cachePool=memcacheStub) self.tokens = {} self.tokens['/calendars/__uids__/cdaboo/'] = 'uriToken0' self.tokens['/calendars/__uids__/cdaboo/calendars/'] = 'childToken0' self.tokens['/principals/__uids__/cdaboo/'] = 'principalToken0' self.tokens['/principals/__uids__/dreid/'] = 'principalTokenX' def _getToken(uri, cachePoolHandle=None): return succeed(self.tokens.get(uri)) self.rc._tokenForURI = _getToken self.expected_response = (200, Headers({}), "Foo") expected_key = hashlib.md5(':'.join([ str(t) for t in ( 'PROPFIND', '/principals/__uids__/cdaboo/', '/calendars/__uids__/cdaboo/', '1', hash('foobar'), ) ])).hexdigest() memcacheStub._cache[expected_key] = ( 0, # flags cPickle.dumps( ('principalToken0', StubDirectoryRecord('cdaboo').cacheToken(), 'uriToken0', { '/calendars/__uids__/cdaboo/calendars/': 'childToken0' }, (self.expected_response[0], dict(list(self.expected_response[1].getAllRawHeaders())), self.expected_response[2])))) self.memcacheStub = memcacheStub
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 _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 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 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 __init__(self, code, headers, body): self.code = code self.headers = Headers(headers) self.body = body self.stream = MemoryStream(body)
def _makeHeaders(self, headers_pairs): headers = Headers() for name, value in headers_pairs: headers.addRawHeader(name, value) return headers
def addressbook_query(self, addressbook_uri, query, got_xml, data, no_init): if not no_init: ''' FIXME: clear address book, possibly by removing mkcol = """<?xml version="1.0" encoding="utf-8" ?> <D:mkcol xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav"> <D:set> <D:prop> <D:resourcetype><D:collection/><C:addressbook/></D:resourcetype> </D:prop> </D:set> </D:mkcol> """ response = yield self.send(SimpleStoreRequest(self, "MKCOL", addressbook_uri, content=mkcol, authPrincipal=self.authPrincipal)) response = IResponse(response) if response.code != responsecode.CREATED: self.fail("MKCOL failed: %s" % (response.code,)) ''' if data: for filename, icaldata in data.iteritems(): request = SimpleStoreRequest( self, "PUT", joinURL(addressbook_uri, filename + ".vcf"), headers=Headers({ "content-type": MimeType.fromString("text/vcard") }), authPrincipal=self.authPrincipal) request.stream = MemoryStream(icaldata) yield self.send(request) else: # Add vcards to addressbook for child in FilePath(self.vcards_dir).children(): if os.path.splitext(child.basename())[1] != ".vcf": continue request = SimpleStoreRequest( self, "PUT", joinURL(addressbook_uri, child.basename()), headers=Headers({ "content-type": MimeType.fromString("text/vcard") }), authPrincipal=self.authPrincipal) request.stream = MemoryStream(child.getContent()) yield self.send(request) request = SimpleStoreRequest(self, "REPORT", addressbook_uri, authPrincipal=self.authPrincipal) request.stream = MemoryStream(query.toxml()) response = yield self.send(request) response = IResponse(response) if response.code != responsecode.MULTI_STATUS: self.fail("REPORT failed: %s" % (response.code, )) returnValue((yield davXMLFromStream(response.stream).addCallback(got_xml)))