[CalendarServer-changes] [10598] CalendarServer/trunk/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jan 29 10:29:58 PST 2013
Revision: 10598
http://trac.calendarserver.org//changeset/10598
Author: cdaboo at apple.com
Date: 2013-01-29 10:29:58 -0800 (Tue, 29 Jan 2013)
Log Message:
-----------
iSchedule DKIM updates.
Modified Paths:
--------------
CalendarServer/trunk/twistedcaldav/scheduling/ischedule/delivery.py
CalendarServer/trunk/twistedcaldav/scheduling/ischedule/dkim.py
CalendarServer/trunk/twistedcaldav/scheduling/ischedule/resource.py
CalendarServer/trunk/twistedcaldav/scheduling/ischedule/test/test_dkim.py
CalendarServer/trunk/twistedcaldav/scheduling/ischedule/xml.py
CalendarServer/trunk/twistedcaldav/stdconfig.py
Modified: CalendarServer/trunk/twistedcaldav/scheduling/ischedule/delivery.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/ischedule/delivery.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/scheduling/ischedule/delivery.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -359,7 +359,6 @@
self.headers = Headers()
self.headers.setHeader("Host", utf8String(host + ":%s" % (port,)))
- self.sign_headers.append("Host")
# The Originator must be the ORGANIZER (for a request) or ATTENDEE (for a reply)
originator = self.scheduler.organizer.cuaddr if self.scheduler.isiTIPRequest else self.scheduler.attendee
@@ -370,8 +369,8 @@
for recipient in self.recipients:
self.headers.addRawHeader("Recipient", utf8String(recipient.cuaddr))
- # Remember to "over sign" the Recipient header
- self.sign_headers.append("Recipient+")
+ # Only one Recipient header as they get concatenated in ischedule-relaxed canonicalization
+ self.sign_headers.append("Recipient")
self._doAuthentication()
Modified: CalendarServer/trunk/twistedcaldav/scheduling/ischedule/dkim.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/ischedule/dkim.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/scheduling/ischedule/dkim.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -33,8 +33,6 @@
from Crypto.Signature import PKCS1_v1_5
import base64
-import binascii
-import collections
import hashlib
import os
import textwrap
@@ -61,9 +59,9 @@
ISCHEDULE_VERSION = "iSchedule-Version"
ISCHEDULE_VERSION_VALUE = "1.0"
ISCHEDULE_MESSAGE_ID = "iSchedule-Message-ID"
+ISCHEDULE_CAPABILITIES = "iSchedule-Capabilities"
-
class DKIMUtils(object):
"""
Some useful functions.
@@ -207,7 +205,18 @@
@staticmethod
- def canonicalizeHeader(name, value, remove_b=None):
+ def canonicalizeHeader(name, value, dkim_tags=None, method="ischedule-relaxed"):
+
+ if method == "relaxed":
+ return DKIMUtils.relaxedHeader(name, value, dkim_tags)
+ elif method == "ischedule-relaxed":
+ return DKIMUtils.ischeduleHeader(name, value, dkim_tags)
+ else:
+ assert "Invalid header canonicalization method: %s" % (method,)
+
+
+ @staticmethod
+ def relaxedHeader(name, value, dkim_tags=None):
"""
Canonicalize the header using "relaxed" method. Optionally remove the b= value from
any DKIM-Signature present.
@@ -220,25 +229,70 @@
@type name: C{str}
@param value: header value
@type value: C{str}
- @param remove_b: the b= value to remove, or C{None} if no removal needed
- @type remove_b: C{str} or C{None}
+ @param dkim_tags: the extracted DKIM tags, or C{None} if no removal needed
+ @type dkim_tags: C{dict} or C{None}
"""
+ # Special case DKIM-Signature: remove the b= value for signature
+ name = name.lower()
+ if dkim_tags is not None and name == DKIM_SIGNATURE.lower():
+ value = DKIMUtils.canonicalizeDKIMHeaderFields(value, dkim_tags)
+
# Basic relaxed behavior
- name = name.lower()
value = " ".join(value.split())
+ crlf = "" if name == DKIM_SIGNATURE.lower() else "\r\n"
+ return "%s:%s%s" % (name, value, crlf)
+
+
+ @staticmethod
+ def ischeduleHeader(name, value, dkim_tags=None):
+ """
+ Canonicalize the header using "ischedule-relaxed" method. Optionally remove the b= value from
+ any DKIM-Signature present.
+
+ FIXME: this needs to be smarter about where valid WSP can occur in a header. Right now it will
+ blindly collapse all runs of SP/HTAB into a single SP. That could be wrong if a legitimate sequence of
+ SP/HTAB occurs in a header value.
+
+ @param name: header name
+ @type name: C{str}
+ @param value: header value
+ @type value: C{str}
+ @param dkim_tags: the extracted DKIM tags, or C{None} if no removal needed
+ @type dkim_tags: C{dict} or C{None}
+ """
+
# Special case DKIM-Signature: remove the b= value for signature
- if remove_b is not None and name == DKIM_SIGNATURE.lower():
- pos = value.find(remove_b)
- value = value[:pos] + value[pos + len(remove_b):]
- value = " ".join(value.split())
+ name = name.lower()
+ if dkim_tags is not None and name == DKIM_SIGNATURE.lower():
+ value = DKIMUtils.canonicalizeDKIMHeaderFields(value, dkim_tags)
+ # Basic relaxed behavior
+ value = " ".join(value.split())
+ value = value.replace(" ,", ",")
+ value = value.replace(", ", ",")
+
crlf = "" if name == DKIM_SIGNATURE.lower() else "\r\n"
return "%s:%s%s" % (name, value, crlf)
@staticmethod
+ def canonicalizeDKIMHeaderFields(value, dkim_tags):
+ """
+ DKIM-Signature b= value needs to be stripped.
+
+ @param value: header value to process
+ @type value: C{str}
+ """
+
+ pos = value.find(dkim_tags["b"])
+ value = value[:pos] + value[pos + len(dkim_tags["b"]):]
+ value = " ".join(value.split())
+ return value
+
+
+ @staticmethod
def canonicalizeBody(data):
if not data.endswith("\r\n"):
data += "\r\n"
@@ -402,13 +456,11 @@
sign_headers = []
raw = dict([(name.lower(), values) for name, values in self.headers.getAllRawHeaders()])
for name in self.sign_headers:
- oversign = name[-1] == "+"
- name = name.rstrip("+")
- for value in reversed(raw.get(name.lower(), ())):
- headers.append(DKIMUtils.canonicalizeHeader(name, value))
- sign_headers.append(name)
- if oversign:
- sign_headers.append(name)
+ # ischedule-relaxed canonicalization requires headers with the same name concatenated
+ # with a comma in between
+ value = ",".join(raw.get(name.lower(), ()))
+ headers.append(DKIMUtils.canonicalizeHeader(name, value))
+ sign_headers.append(name)
# Generate the DKIM header tags we care about
dkim_tags = []
@@ -419,8 +471,7 @@
dkim_tags.append(("x", self.expire,))
dkim_tags.append(("a", self.algorithm,))
dkim_tags.append(("q", ":".join(self.keyMethods),))
- dkim_tags.append(("http", base64.encodestring("%s:%s" % (self.method, self.uri,)).strip()))
- dkim_tags.append(("c", "relaxed/simple",))
+ dkim_tags.append(("c", "ischedule-relaxed/simple",))
dkim_tags.append(("h", ":".join(sign_headers),))
dkim_tags.append(("bh", (yield self.bodyHash()),))
dkim_tags.append(("b", "",))
@@ -501,7 +552,7 @@
# Do header verification
try:
- DKIMUtils.verify(headers, self.dkim_tags["b"], pubkey, self.hash_func)
+ DKIMUtils.verify(headers, self.dkim_tags["_b"], pubkey, self.hash_func)
except ValueError:
msg = "Could not verify signature"
_debug_msg = """
@@ -524,7 +575,7 @@
self.request.stream.doStartReading = None
body = DKIMUtils.canonicalizeBody(data)
bh = base64.b64encode(self.hash_method(body).digest())
- if bh != self.dkim_tags["bh"]:
+ if bh != self.dkim_tags["_bh"]:
msg = "Could not verify the DKIM body hash"
_debug_msg = """
DKIM-Signature:%s
@@ -566,7 +617,7 @@
self.dkim_tags = DKIMUtils.extractTags(dkim)
# Verify validity of tags
- required_tags = ("v", "a", "b", "bh", "c", "d", "h", "s", "http",)
+ required_tags = ("v", "a", "b", "bh", "c", "d", "h", "s",)
for tag in required_tags:
if tag not in self.dkim_tags:
msg = "Missing DKIM-Signature tag: %s" % (tag,)
@@ -576,7 +627,7 @@
check_values = {
"v": ("1",),
"a": (RSA1, RSA256,),
- "c": ("relaxed", "relaxed/simple",),
+ "c": ("ischedule-relaxed", "ischedule-relaxed/simple",),
"q": (Q_DNS, Q_HTTP, Q_PRIVATE,),
}
for tag, values in check_values.items():
@@ -594,6 +645,14 @@
log.debug("DKIM: " + msg)
raise DKIMVerificationError(msg)
+ # Check time stamp
+ if "t" in self.dkim_tags:
+ diff_time = self.time - int(self.dkim_tags["t"])
+ if diff_time < -360:
+ msg = "Signature time to far in the future: %d seconds" % (diff_time,)
+ log.debug("DKIM: " + msg)
+ raise DKIMVerificationError(msg)
+
# Check expiration
if "x" in self.dkim_tags:
diff_time = self.time - int(self.dkim_tags["x"])
@@ -602,27 +661,9 @@
log.debug("DKIM: " + msg)
raise DKIMVerificationError(msg)
- # Check HTTP method/request-uri
- try:
- http_tag = base64.decodestring(self.dkim_tags["http"])
- except binascii.Error:
- msg = "Tag: http is not valid base64"
- log.debug("DKIM: " + msg)
- raise DKIMVerificationError(msg)
- try:
- method, uri = http_tag.split(":", 1)
- except ValueError:
- msg = "Tag: base64-decoded http is not valid: %s" % (http_tag,)
- log.debug("DKIM: " + msg)
- raise DKIMVerificationError(msg)
- if method != self.request.method:
- msg = "Tag: http method does not match: %s" % (method,)
- log.debug("DKIM: " + msg)
- raise DKIMVerificationError(msg)
- if uri != self.request.uri:
- msg = "Tag: http request-URI does not match: %s" % (uri,)
- log.debug("DKIM: " + msg)
- raise DKIMVerificationError(msg)
+ # Base64 encoded tags might include WSP which we need to ignore
+ for tag in ("b", "bh",):
+ self.dkim_tags["_%s" % (tag,)] = "".join(self.dkim_tags[tag].split())
# Some useful bits
self.hash_method = DKIMUtils.hashlib_method(self.dkim_tags["a"])
@@ -636,26 +677,21 @@
and return the expected signed data.
"""
- # Extract all the expected signed headers taking into account the possibility of "over_counting"
- # headers - a technique used to ensure headers cannot be added in transit
+ # Extract all the expected signed headers taking into account multiple occurrences of a header
+ # which get concatenated with a single comma in between.
header_list = [hdr.strip() for hdr in self.dkim_tags["h"].split(":")]
- header_counter = collections.defaultdict(int)
headers = []
for header in header_list:
actual_headers = self.request.headers.getRawHeaders(header)
if actual_headers:
- try:
- headers.append((header, actual_headers[-1 - header_counter[header]],))
- except IndexError:
- pass
- header_counter[header] += 1
+ headers.append((header, ",".join(actual_headers),))
# DKIM-Signature is always included at the end
headers.append((DKIM_SIGNATURE, self.request.headers.getRawHeaders(DKIM_SIGNATURE)[0],))
# Now canonicalize the values
- return "".join([DKIMUtils.canonicalizeHeader(name, value, remove_b=self.dkim_tags["b"]) for name, value in headers])
+ return "".join([DKIMUtils.canonicalizeHeader(name, value, dkim_tags=self.dkim_tags) for name, value in headers])
@inlineCallbacks
Modified: CalendarServer/trunk/twistedcaldav/scheduling/ischedule/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/ischedule/resource.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/scheduling/ischedule/resource.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -30,6 +30,7 @@
from twistedcaldav.scheduling.ischedule.scheduler import IScheduleScheduler
from txdav.xml import element as davxml
import twistedcaldav.scheduling.ischedule.xml as ischedulexml
+from twistedcaldav.scheduling.ischedule.dkim import ISCHEDULE_CAPABILITIES
__all__ = [
"IScheduleInboxResource",
@@ -156,6 +157,7 @@
result = ischedulexml.QueryResult(
ischedulexml.Capabilities(
+ ischedulexml.Version.fromString(config.Scheduling.iSchedule.SerialNumber),
ischedulexml.Versions(
ischedulexml.Version.fromString("1.0"),
),
@@ -194,7 +196,9 @@
ischedulexml.Administrator.fromString(request.unparseURL(params="", querystring="", fragment="")),
),
)
- return XMLResponse(responsecode.OK, result)
+ response = XMLResponse(responsecode.OK, result)
+ response.headers.addRawHeader(ISCHEDULE_CAPABILITIES, str(config.Scheduling.iSchedule.SerialNumber))
+ return response
@inlineCallbacks
@@ -218,7 +222,9 @@
raise e
else:
yield txn.commit()
- returnValue(result.response())
+ response = result.response()
+ response.headers.addRawHeader(ISCHEDULE_CAPABILITIES, str(config.Scheduling.iSchedule.SerialNumber))
+ returnValue(response)
##
# ACL
Modified: CalendarServer/trunk/twistedcaldav/scheduling/ischedule/test/test_dkim.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/ischedule/test/test_dkim.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/scheduling/ischedule/test/test_dkim.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -149,7 +149,7 @@
recipient:mailto:user02 at example.com
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; http=UE9TVDov; c=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)
+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)
@@ -183,7 +183,7 @@
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; http=UE9TVDov; c=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)
+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)
self.assertEqual(result, sign_this)
@@ -211,14 +211,14 @@
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; http=UE9TVDov; c=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)
+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; http=UE9TVDov; c=relaxed/simple; h=Originator:Recipient:Content-Type:iSchedule-Version:iSchedule-Message-ID; bh=%s; b=%s" % (request.time, request.expire, algorithm, bodyhash, signature,)
+ 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
@@ -254,24 +254,24 @@
# More than one
((
- ("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http/well-known; http=UE9TVDov; c=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; http=UE9TVDov; c=relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),
+ ("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; http=UE9TVDov; c=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; http=UE9TVDov; c=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; http=UE9TVDov; c=relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() + 30),)),), True,),
+ ((("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; http=UE9TVDov; c=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; http=UE9TVDov; c=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; http=UE9TVDov; c=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; http=UE9TVDov; c=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; http=UE9TVDov; c=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=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; http=UE9TVDovaXNjaGVkdWxl; c=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; http=POST:/; c=relaxed; h=Originator:Recipient; bh=abc; b=def" % (int(time.time() - 30),)),), False,),
+ ((("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:
@@ -291,17 +291,17 @@
data = (
("Content-Type", " text/calendar ; charset = \"utf-8\" ", "content-type:text/calendar ; charset = \"utf-8\"\r\n"),
("Originator", " mailto:user01 at example.com ", "originator:mailto:user01 at example.com\r\n"),
- ("Recipient", " mailto:user02 at example.com ,\t mailto:user03 at example.com\t\t ", "recipient:mailto:user02 at example.com , mailto:user03 at example.com\r\n"),
+ ("Recipient", " mailto:user02 at example.com ,\t mailto:user03 at example.com\t\t ", "recipient:mailto:user02 at example.com,mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def",
- "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=",
+ " 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 ; http=\tUE9TVDov ; c=relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc",
- "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; b= ; http= UE9TVDov ; c=relaxed/simple; h=Originator:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc",
+ " 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",
),
)
@@ -310,7 +310,7 @@
verifier = DKIMVerifier(request)
if name == "DKIM-Signature":
verifier.processDKIMHeader()
- canonicalized = DKIMUtils.canonicalizeHeader(name, value, remove_b=verifier.dkim_tags["b"] if name == "DKIM-Signature" else None)
+ canonicalized = DKIMUtils.canonicalizeHeader(name, value, verifier.dkim_tags if name == "DKIM-Signature" else None)
self.assertEqual(canonicalized, result)
@@ -320,21 +320,21 @@
"""
data = (
- # Over count on Recipient
+ # Count on Recipient
("""Host:example.com
Content-Type: text/calendar ; charset = "utf-8"
Originator: mailto:user01 at example.com
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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:user01 at example.com
-recipient:mailto:user02 at example.com , mailto:user03 at example.com
+recipient:mailto:user02 at example.com,mailto:user03 at example.com
ischedule-version:1.0
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
+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
@@ -343,51 +343,31 @@
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\t\t
Recipient:\t\t mailto:user04 at example.com
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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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:user01 at example.com
-recipient:mailto:user04 at example.com
-recipient:mailto:user02 at example.com , mailto:user03 at example.com
+recipient:mailto:user02 at example.com,mailto:user03 at example.com,mailto:user04 at example.com
ischedule-version:1.0
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
+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="""
),
- # Under count on Recipient
- ("""Host:example.com
-Content-Type: text/calendar ; charset = "utf-8"
-iSchedule-Version: 1.0
-Originator: mailto:user01 at example.com
-Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\t\t
-Recipient:\t\t mailto:user04 at example.com
-Recipient:\t\t mailto:user05 at example.com
-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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient: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:user01 at example.com
-recipient:mailto:user05 at example.com
-recipient:mailto:user04 at example.com
-ischedule-version:1.0
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
- ),
# Re-ordered Content-Type
("""Host:example.com
iSchedule-Version: 1.0
Originator: mailto:user01 at example.com
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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:user01 at example.com
-recipient:mailto:user02 at example.com , mailto:user03 at example.com
+recipient:mailto:user02 at example.com,mailto:user03 at example.com
ischedule-version:1.0
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http/well-known ; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b="""
+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="""
),
)
@@ -411,7 +391,7 @@
Content-Type: text/calendar ; charset = "utf-8"
Originator: mailto:user01 at example.com
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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
""",
@@ -423,7 +403,7 @@
Content-Type: text/calendar ; charset = "utf-8"
Originator: mailto:user01 at example.com
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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
""",
@@ -435,7 +415,7 @@
Content-Type: text/calendar ; charset = "utf-8"
Originator: mailto:user01 at example.com
Recipient: mailto:user02 at example.com ,\t mailto:user03 at example.com\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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
+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
""",
@@ -574,7 +554,7 @@
manipulate_request=lambda request: setattr(request, "stream", MemoryStream("BEGIN:DATA\n")),
)
- # Valid - extra header no over sign
+ # Invalid - extra header
yield _verify(
"""Host:example.com
Content-Type: text/calendar ; charset = "utf-8"
@@ -587,11 +567,11 @@
END:DATA
""",
[DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
- True,
+ False,
manipulate_request=lambda request: request.headers.getRawHeaders("Recipient").insert(0, "mailto:user04 at example.com"),
)
- # Valid - over sign header
+ # Valid - header
yield _verify(
"""Host:example.com
Content-Type: text/calendar ; charset = "utf-8"
@@ -604,8 +584,8 @@
END:DATA
""",
[DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
- False,
- sign_headers=("Originator", "Recipient", "Recipient", "Content-Type",),
+ True,
+ sign_headers=("Originator", "Recipient", "Content-Type",),
)
# Invalid - over sign header extra header
@@ -622,7 +602,7 @@
""",
[DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))],
False,
- sign_headers=("Originator", "Recipient", "Recipient", "Content-Type",),
+ sign_headers=("Originator", "Recipient", "Content-Type",),
manipulate_request=lambda request: request.headers.addRawHeader("Recipient", ("mailto:user04 at example.com",))
)
Modified: CalendarServer/trunk/twistedcaldav/scheduling/ischedule/xml.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/ischedule/xml.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/scheduling/ischedule/xml.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -48,6 +48,7 @@
name = "capabilities"
allowed_children = {
+ (ischedule_namespace, "serial-number"): (1, 1),
(ischedule_namespace, "versions"): (1, 1),
(ischedule_namespace, "scheduling-messages"): (1, 1),
(ischedule_namespace, "calendar-data-types"): (1, 1),
@@ -64,6 +65,13 @@
@registerElement
+class SerialNumber (WebDAVTextElement):
+ namespace = ischedule_namespace
+ name = "serial-number"
+
+
+
+ at registerElement
class Versions (WebDAVElement):
namespace = ischedule_namespace
name = "versions"
Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py 2013-01-29 18:28:17 UTC (rev 10597)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py 2013-01-29 18:29:58 UTC (rev 10598)
@@ -641,6 +641,7 @@
"Enabled" : False, # iSchedule protocol
"AddressPatterns" : [], # Reg-ex patterns to match iSchedule-able calendar user addresses
"RemoteServers" : "remoteservers.xml", # iSchedule server configurations
+ "SerialNumber" : 1, # Capabilities serial number
"DNSDebug" : "", # File where a fake Bind zone exists for creating fake DNS results
"DKIM" : { # DKIM options
"Enabled" : True, # DKIM signing/verification enabled
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130129/02334928/attachment-0001.html>
More information about the calendarserver-changes
mailing list