[CalendarServer-changes] [9766] CalendarServer/branches/users/cdaboo/ischedule-dkim
source_changes at macosforge.org
source_changes at macosforge.org
Tue Sep 4 08:24:12 PDT 2012
Revision: 9766
http://trac.macosforge.org/projects/calendarserver/changeset/9766
Author: cdaboo at apple.com
Date: 2012-09-04 08:24:11 -0700 (Tue, 04 Sep 2012)
Log Message:
-----------
Update to latest iSchedule spec. Add a dkimtool to do command line key-gen, request generation, request verification.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/__init__.py
CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py
CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/test/test_dkim.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py
Added: CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py 2012-09-04 15:24:11 UTC (rev 9766)
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+##
+# Copyright (c) 2012 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from StringIO import StringIO
+from subprocess import PIPE
+from twext.web2.http_headers import Headers
+from twext.web2.stream import MemoryStream
+from twisted.internet import reactor
+from twisted.internet.defer import inlineCallbacks
+from twisted.python.usage import Options
+from twistedcaldav.scheduling.ischedule.dkim import RSA256, DKIMRequest,\
+ PublicKeyLookup, DKIMVerifier, DKIMVerificationError
+import subprocess
+import sys
+from twext.web2.client.http import ClientRequest
+import rsa
+
+
+def _doKeyGeneration(options):
+ child = subprocess.Popen(
+ args=["openssl", "genrsa", str(options["key-size"]),],
+ stdout=PIPE,
+ )
+ output, status = child.communicate()
+ if status:
+ print "Failed to generate private key"
+ sys.exit(1)
+ output = output.strip()
+ if options["key"]:
+ open(options["key"], "w").write(output)
+ else:
+ print output
+
+ child = subprocess.Popen(
+ args=["openssl", "rsa", "-pubout",],
+ stdout=PIPE,
+ stdin=PIPE,
+ )
+ output, status = child.communicate(output)
+ if status:
+ print "Failed to generate public key"
+ sys.exit(1)
+ output = output.strip()
+ if options["pub-key"]:
+ open(options["pub-key"], "w").write(output)
+ else:
+ print output
+
+ if options["txt"]:
+ output = "".join(output.splitlines()[1:-1])
+ txt = "v=DKIM1; p=%s" % (output,)
+ print txt
+
+ at inlineCallbacks
+def _doRequest(options):
+
+ # Parse the HTTP file
+ request = open(options["request"]).read()
+ method, uri, headers, stream = _parseRequest(request)
+
+ # Setup signing headers
+ sign_headers = options["signing"]
+ if sign_headers is None:
+ sign_headers = []
+ for hdr in ("Host", "Content-Type", "Originator", "Recipient+"):
+ if headers.hasHeader(hdr.rstrip("+")):
+ sign_headers.append(hdr)
+ else:
+ sign_headers = sign_headers.split(":")
+
+ dkim = DKIMRequest(
+ method,
+ uri,
+ headers,
+ stream,
+ options["domain"],
+ options["selector"],
+ options["key"],
+ options["algorithm"],
+ sign_headers,
+ True,
+ True,
+ int(options["expire"]),
+ )
+ yield dkim.sign()
+
+ s = StringIO()
+ _writeRequest(dkim, s)
+ print s.getvalue()
+
+
+ at inlineCallbacks
+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)
+
+ try:
+ yield dkim.verify()
+ except DKIMVerificationError, e:
+ print "Verification Failed: %s" % (e,)
+ else:
+ print "Verification Succeeded"
+
+
+def _parseRequest(request):
+
+ lines = request.replace("\r\n", "\n").splitlines()
+
+ 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 == "":
+ 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.lstrip())
+
+ stream = MemoryStream("\r\n".join(body))
+
+ return method, uri, headers, stream
+
+
+def _writeRequest(request, f):
+
+ f.write("%s %s HTTP/1.1\r\n" % (request.method, request.uri,))
+ for name, valuelist in request.headers.getAllRawHeaders():
+ for value in valuelist:
+ f.write("%s: %s\r\n" % (name, value))
+ f.write("\r\n")
+ f.write(request.stream.read())
+
+
+class PublicKeyLookup_File(PublicKeyLookup):
+
+ method = "*"
+ pubkeyfile = None
+
+ def getPublicKey(self):
+ """
+ Do the key lookup using the actual lookup method.
+ """
+ return rsa.PublicKey.load_pkcs1(open(self.pubkeyfile).read())
+
+
+def usage(e=None):
+ if e:
+ print e
+ print ""
+ try:
+ DKIMToolOptions().opt_help()
+ except SystemExit:
+ pass
+ if e:
+ sys.exit(64)
+ else:
+ sys.exit(0)
+
+
+description = """Usage: dkimtool [options]
+Options:
+ -h Print this help and exit
+
+ # Key Generation
+ --key-gen Generate private/public key files
+ --key FILE Private key file to create [stdout]
+ --pub-key FILE Public key file to create [stdout]
+ --key-size SIZE Key size [1024]
+ --txt Also generate the public key TXT record
+
+ # Request
+ --request FILE An HTTP request to sign
+ --algorithm ALGO Signature algorithm [rsa-sha256]
+ --domain DOMAIN Signature domain [example.com]
+ --selector SELECTOR Signature selector [dkim]
+ --key FILE Private key to use
+ --signing HEADERS List of headers to sign [automatic]
+ --expire SECONDS When to expire signature [no expiry]
+
+ # Verify
+ --verify FILE An HTTP request to verify
+ --pkey FILE Public key to use in place of
+ q= lookup
+
+Description:
+ This utility is for testing DKIM signed HTTP request.
+
+"""
+
+
+class DKIMToolOptions(Options):
+ """
+ Command-line options for 'calendarserver_dkimtool'
+ """
+
+ synopsis = description
+
+ optFlags = [
+ ['verbose', 'v', "Verbose logging."],
+ ['key-gen', 'g', "Generate private/public key files"],
+ ['txt', 't', "Also generate the public key TXT record"],
+ ]
+
+ optParameters = [
+ ['key', 'k', None, "Private key file to create [default: stdout]"],
+ ['pub-key', 'p', None, 'Public key file to create [default: stdout]'],
+ ['key-size', 'x', 1024, 'Key size'],
+ ['request', 'r', None, 'An HTTP request to sign'],
+ ['algorithm', 'a', RSA256, 'Signature algorithm'],
+ ['domain', 'd', 'example.com', 'Signature domain'],
+ ['selector', 's', 'dkim', 'Signature selector'],
+ ['signing', 'h', None, 'List of headers to sign [automatic]'],
+ ['expire', 'e', 3600, 'When to expire signature'],
+ ['verify', 'w', None, 'An HTTP request to verify'],
+ ]
+
+ def __init__(self):
+ super(DKIMToolOptions, self).__init__()
+ self.outputName = '-'
+
+
+ at inlineCallbacks
+def _runInReactor(fn, options):
+
+ try:
+ yield fn(options)
+ except Exception, e:
+ print e
+ finally:
+ reactor.stop()
+
+
+def main(argv=sys.argv, stderr=sys.stderr):
+ options = DKIMToolOptions()
+ options.parseOptions(argv[1:])
+
+ if options["key-gen"]:
+ _doKeyGeneration(options)
+ elif options["request"]:
+ reactor.callLater(0, _runInReactor, _doRequest, options)
+ reactor.run()
+ elif options["verify"]:
+ reactor.callLater(0, _runInReactor, _doVerify, options)
+ reactor.run()
+ else:
+ usage("Invalid options")
+
+if __name__ == '__main__':
+ main()
Property changes on: CalendarServer/branches/users/cdaboo/ischedule-dkim/calendarserver/tools/dkimtool.py
___________________________________________________________________
Added: svn:executable
+ *
Modified: CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/__init__.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/__init__.py 2012-09-01 00:56:43 UTC (rev 9765)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/__init__.py 2012-09-04 15:24:11 UTC (rev 9766)
@@ -14,6 +14,13 @@
# limitations under the License.
##
+
"""
iSchedule scheduling.
"""
+
+from twext.web2 import http_headers
+
+# These new HTTP headers should appear with case-preserved
+hdrs = ("iSchedule-Version", "iSchedule-Message-ID", "DKIM-Signature",)
+http_headers.casemappingify(dict([(i, i) for i in hdrs]))
Modified: CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py 2012-09-01 00:56:43 UTC (rev 9765)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/dkim.py 2012-09-04 15:24:11 UTC (rev 9766)
@@ -20,11 +20,13 @@
from twext.web2.stream import MemoryStream
from twisted.internet.defer import inlineCallbacks, returnValue
import base64
+import binascii
import collections
import hashlib
import rsa
import textwrap
import time
+import uuid
"""
DKIM HTTP message generation and validation,
@@ -32,7 +34,20 @@
log = Logger()
+# DKIM/iSchedule Constants
+RSA1 = "rsa-sha1"
+RSA256 = "rsa-sha256"
+Q_DNS = "dns/txt"
+Q_HTTP = "http/well-known"
+KEY_SERVICE_TYPE = "ischedule"
+
+# Headers
+DKIM_SIGNATURE = "DKIM-Signature"
+ISCHEDULE_VERSION = "iSchedule-Version"
+ISCHEDULE_VERSION_VALUE = "1.0"
+ISCHEDULE_MESSAGE_ID = "iSchedule-Message-ID"
+
class DKIMUtils(object):
"""
Some useful functions.
@@ -44,8 +59,8 @@
Return hashlib function for DKIM algorithm.
"""
return {
- "rsa-sha1" : hashlib.sha1,
- "rsa-sha256": hashlib.sha256,
+ RSA1 : hashlib.sha1,
+ RSA256: hashlib.sha256,
}[algorithm]
@staticmethod
@@ -54,8 +69,8 @@
Return RSA hash name for DKIM algorithm.
"""
return {
- "rsa-sha1" : "SHA-1",
- "rsa-sha256": "SHA-256"
+ RSA1 : "SHA-1",
+ RSA256: "SHA-256"
}[algorithm]
@@ -95,7 +110,7 @@
value = " ".join(value.split())
# Special case DKIM-Signature: remove the b= value for signature
- if remove_b is not None and name == "dkim-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())
@@ -126,6 +141,34 @@
useHTTPKey,
expire,
):
+ """
+ Create a DKIM request, which is a regular client request with the additional information needed to sign the message.
+
+ @param method: HTTP method to use
+ @type method: C{str}
+ @param uri: request-URI
+ @type uri: C{str}
+ @param headers: request headers
+ @type headers: L{http_headers}
+ @param stream: body data
+ @type stream: L{Stream}
+ @param domain: the signing domain
+ @type domain: C{str}
+ @param selector: the signing key selector
+ @type selector: C{str}
+ @param key_file: path to a private key file
+ @type key_file: C{str}
+ @param algorithm: the signing algorithm to use
+ @type algorithm: C{str}
+ @param sign_headers: list of header names to sign - to "over sign" a header append a "+" to the name
+ @type sign_headers: C{tuple}
+ @param useDNSKey: whether or not to add DNS TXT lookup as a key lookup option
+ @type useDNSKey: C{bool}
+ @param useHTTPKey: whether or not to add HTTP .well-known as a key lookup option
+ @type useHTTPKey: C{bool}
+ @param expire: number of seconds to expiration of signature
+ @type expire: C{int}
+ """
super(DKIMRequest, self).__init__(method, uri, headers, stream)
self.domain = domain
self.selector = selector
@@ -137,15 +180,17 @@
assert self.domain
assert self.selector
- assert self.algorithm in ("rsa-sha1", "rsa-sha256",)
+ assert self.algorithm in (RSA1, RSA256,)
assert useDNSKey or useHTTPKey
self.hash_method = DKIMUtils.hashlib_method(self.algorithm)
self.hash_name = DKIMUtils.hash_name(self.algorithm)
self.keyMethods = []
- if useDNSKey: self.keyMethods.append("dns/txt")
- if useHTTPKey: self.keyMethods.append("http-well-known")
+ if useDNSKey: self.keyMethods.append(Q_DNS)
+ if useHTTPKey: self.keyMethods.append(Q_HTTP)
+
+ self.message_id = str(uuid.uuid4())
@inlineCallbacks
@@ -164,7 +209,7 @@
# Complete the header
dkim_tags[-1] = ("b", signature,)
dkim_header = "; ".join(["%s=%s" % item for item in dkim_tags])
- self.headers.addRawHeader("DKIM-Signature", dkim_header)
+ self.headers.addRawHeader(DKIM_SIGNATURE, dkim_header)
log.debug("DKIM: Generated header: DKIM-Signature:%s" % (dkim_header,))
log.debug("DKIM: Signed headers:\n%s" % (headers,))
@@ -194,14 +239,23 @@
Generate the headers that are going to be signed as well as the DKIM-Signature tags.
"""
+ # Make sure we have the required iSchedule headers
+ self.headers.addRawHeader(ISCHEDULE_VERSION, ISCHEDULE_VERSION_VALUE)
+ self.headers.addRawHeader(ISCHEDULE_MESSAGE_ID, self.message_id)
+ self.sign_headers += (ISCHEDULE_VERSION, ISCHEDULE_MESSAGE_ID,)
+
# Figure out all the existing headers to sign
headers = []
sign_headers = []
- raw = dict([(name, values) for name, values in self.headers.getAllRawHeaders()])
+ raw = dict([(name.lower(), values) for name, values in self.headers.getAllRawHeaders()])
for name in self.sign_headers:
- for value in raw[name]:
+ oversign = name[-1] == "+"
+ name = name.rstrip("+")
+ for value in raw.get(name.lower(), ()):
headers.append(DKIMUtils.canonicalizeHeader(name, value))
sign_headers.append(name)
+ if oversign:
+ sign_headers.append(name)
# Generate the DKIM header tags we care about
dkim_tags = []
@@ -212,13 +266,14 @@
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(("h", ":".join(sign_headers),))
dkim_tags.append(("bh", (yield self.bodyHash()),))
dkim_tags.append(("b", "",))
dkim_header = "; ".join(["%s=%s" % item for item in dkim_tags])
- headers.append(DKIMUtils.canonicalizeHeader("DKIM-Signature", dkim_header))
+ headers.append(DKIMUtils.canonicalizeHeader(DKIM_SIGNATURE, dkim_header))
headers = "".join(headers)
returnValue((headers, dkim_tags,))
@@ -282,8 +337,9 @@
try:
rsa.verify(headers, base64.b64decode(self.dkim_tags["b"]), pubkey)
except rsa.VerificationError:
- log.debug("DKIM: Could not verify signature: DKIM-Signature:%s" % (self.request.headers.getRawHeaders("DKIM-Signature"),))
- raise DKIMVerificationError("Could not verify the DKIM signature")
+ msg = "Could not verify signature"
+ log.debug("DKIM: %s: DKIM-Signature:%s" % (msg, self.request.headers.getRawHeaders(DKIM_SIGNATURE),))
+ raise DKIMVerificationError(msg)
# Do body validation
data = (yield allDataFromStream(self.request.stream))
@@ -291,8 +347,9 @@
self.request.stream.doStartReading = None
bh = base64.b64encode(self.hash_method(data).digest())
if bh != self.dkim_tags["bh"]:
- log.debug("DKIM: Could not verify body hash: DKIM-Signature:%s" % (self.request.headers.getRawHeaders("DKIM-Signature"),))
- raise DKIMVerificationError("Could not verify the DKIM body hash")
+ msg = "Could not verify the DKIM body hash"
+ log.debug("DKIM: %s: DKIM-Signature:%s" % (msg, self.request.headers.getRawHeaders(DKIM_SIGNATURE),))
+ raise DKIMVerificationError(msg)
def processDKIMHeader(self):
@@ -303,15 +360,17 @@
"""
# Check presence of header
- dkim = self.request.headers.getRawHeaders("DKIM-Signature")
+ dkim = self.request.headers.getRawHeaders(DKIM_SIGNATURE)
if dkim is None:
- log.debug("DKIM: No DKIM-Signature header present in the request")
- raise DKIMVerificationError("No DKIM-Signature header present in the request")
+ msg = "No DKIM-Signature header present in the request"
+ log.debug("DKIM: " + msg)
+ raise DKIMVerificationError(msg)
if len(dkim) != 1:
# TODO: This might need to be changed if we ever support forwarding of iSchedule messages - the forwarder
# might also sign the message and add its own header
- log.debug("DKIM: Only one DKIM-Signature allowed in the request")
- raise DKIMVerificationError("Only one DKIM-Signature allowed in the request")
+ msg = "Only one DKIM-Signature allowed in the request"
+ log.debug("DKIM: " + msg)
+ raise DKIMVerificationError(msg)
dkim = dkim[0]
log.debug("DKIM: Found header: DKIM-Signature:%s" % (dkim,))
@@ -319,17 +378,18 @@
self.dkim_tags = DKIMUtils.extractTags(dkim)
# Verify validity of tags
- required_tags = ("v", "a", "b", "bh", "c", "d", "h", "s",)
+ required_tags = ("v", "a", "b", "bh", "c", "d", "h", "s", "http",)
for tag in required_tags:
if tag not in self.dkim_tags:
- log.debug("DKIM: Missing DKIM-Signature tag: %s" % (tag,))
- raise DKIMVerificationError("Missing DKIM-Signature tag: %s" % (tag,))
+ msg = "Missing DKIM-Signature tag: %s" % (tag,)
+ log.debug("DKIM: " + msg)
+ raise DKIMVerificationError(msg)
check_values = {
"v": ("1",),
- "a": ("rsa-sha1", "rsa-sha256",),
+ "a": (RSA1, RSA256,),
"c": ("relaxed", "relaxed/simple",),
- "q": ("dns/txt", "http-well-known",),
+ "q": (Q_DNS, Q_HTTP,),
}
for tag, values in check_values.items():
if tag not in required_tags and tag not in self.dkim_tags:
@@ -342,16 +402,41 @@
test = (self.dkim_tags[tag],)
for item in test:
if item not in values:
- log.debug("DKIM: Tag: %s has incorrect value: %s" % (tag, self.dkim_tags[tag],))
- raise DKIMVerificationError("DKIM-Signature tag: %s has incorrect value: %s" % (tag, self.dkim_tags[tag],))
+ msg = "Tag: %s has incorrect value: %s" % (tag, self.dkim_tags[tag],)
+ log.debug("DKIM: " + msg)
+ raise DKIMVerificationError(msg)
# Check expiration
if "x" in self.dkim_tags:
diff_time = int(time.time()) - int(self.dkim_tags["x"])
if diff_time > 0:
- log.debug("DKIM: Signature expired: %d seconds" % (diff_time,))
- raise DKIMVerificationError("DKIM-Signature expired: %d seconds" % (diff_time,))
+ msg = "Signature expired: %d seconds" % (diff_time,)
+ 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)
+
+
# Some useful bits
self.hash_method = DKIMUtils.hashlib_method(self.dkim_tags["a"])
self.key_methods = self.dkim_tags["q"].split(":")
@@ -371,14 +456,15 @@
headers = []
for header in header_list:
actual_headers = self.request.headers.getRawHeaders(header)
- try:
- headers.append((header, actual_headers[header_counter[header]],))
- except IndexError:
- pass
+ if actual_headers:
+ try:
+ headers.append((header, actual_headers[header_counter[header]],))
+ except IndexError:
+ pass
header_counter[header] += 1
# DKIM-Signature is always included at the end
- headers.append(("DKIM-Signature", self.request.headers.getRawHeaders("DKIM-Signature")[0],))
+ 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])
@@ -391,7 +477,7 @@
"""
for lookup in self.key_lookup_methods:
- if lookup.method in self.key_methods:
+ if lookup.method in self.key_methods or lookup.method == "*":
pubkey = (yield lookup(self.dkim_tags).getPublicKey())
if pubkey is not None:
returnValue(pubkey)
@@ -401,7 +487,10 @@
class PublicKeyLookup(object):
"""
- Abstract base class for public key lookup methods
+ Abstract base class for public key lookup methods.
+
+ The L{method} attribute indicated the DKIM q= lookup method that the class will support, or if set to "*",
+ the class will handle any q= value.
"""
keyCache = {}
@@ -419,15 +508,15 @@
@param useCache: whether or not to use the cache
@type useCache: C{bool}
"""
- key = self.getSelectorKey()
+ key = self._getSelectorKey()
if key not in PublicKeyLookup.keyCache or not useCache:
- pubkeys = (yield self.lookupKeys())
+ pubkeys = (yield self._lookupKeys())
PublicKeyLookup.keyCache[key] = pubkeys
- returnValue(self.selectKey())
+ returnValue(self._selectKey())
- def getSelectorKey(self):
+ def _getSelectorKey(self):
"""
Get a token used to uniquely identify the key being looked up. Token format will
depend on the lookup method.
@@ -435,7 +524,7 @@
raise NotImplementedError
- def lookupKeys(self):
+ def _lookupKeys(self):
"""
Do the key lookup using the actual lookup method. Return a C{list} of C{dict}
that contains the key tag-list. Return a L{Deferred}.
@@ -443,12 +532,12 @@
raise NotImplementedError
- def selectKey(self):
+ def _selectKey(self):
"""
Select a specific key from the list that best matches the DKIM-Signature tags
"""
- pubkeys = PublicKeyLookup.keyCache.get(self.getSelectorKey(), [])
+ pubkeys = PublicKeyLookup.keyCache.get(self._getSelectorKey(), [])
for pkey in pubkeys:
# Check validity
if pkey.get("v", "DKIM1") != "DKIM1":
@@ -464,20 +553,20 @@
continue
# Service type
- if pkey.get("s", "ischedule") not in ("*", "ischedule",):
+ if pkey.get("s", KEY_SERVICE_TYPE) not in ("*", KEY_SERVICE_TYPE,):
continue
# Non-revoked key
if len(pkey.get("p", "")) == 0:
continue
- return self.makeKey(pkey)
+ return self._makeKey(pkey)
- log.debug("DKIM: No valid public key: %s %s" % (self.getSelectorKey(), pubkeys,))
+ log.debug("DKIM: No valid public key: %s %s" % (self._getSelectorKey(), pubkeys,))
return None
- def makeKey(self, pkey):
+ def _makeKey(self, pkey):
"""
Turn the key tag list into an actual RSA public key object
@@ -504,10 +593,10 @@
class PublicKeyLookup_DNSTXT(PublicKeyLookup):
- method = "dns/txt"
+ method = Q_DNS
- def getSelectorKey(self):
+ def _getSelectorKey(self):
"""
Get a token used to uniquely identify the key being looked up. Token format will
depend on the lookup method.
@@ -515,7 +604,7 @@
return "%s._domainkey.%s" % (self.dkim_tags["s"], self.dkim_tags["d"],)
- def lookupKeys(self):
+ def _lookupKeys(self):
"""
Do the key lookup using the actual lookup method.
"""
@@ -526,10 +615,10 @@
class PublicKeyLookup_HTTP_WellKnown(PublicKeyLookup):
- method = "http-well-known"
+ method = Q_HTTP
- def getSelectorKey(self):
+ def _getSelectorKey(self):
"""
Get a token used to uniquely identify the key being looked up. Token format will
depend on the lookup method.
@@ -537,7 +626,7 @@
return "https://%s/.well-known/domainkey/%s" % (self.dkim_tags["d"], self.dkim_tags["s"],)
- def lookupKeys(self):
+ def _lookupKeys(self):
"""
Do the key lookup using the actual lookup method.
"""
Modified: CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/test/test_dkim.py
===================================================================
--- CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/test/test_dkim.py 2012-09-01 00:56:43 UTC (rev 9765)
+++ CalendarServer/branches/users/cdaboo/ischedule-dkim/twistedcaldav/scheduling/ischedule/test/test_dkim.py 2012-09-04 15:24:11 UTC (rev 9766)
@@ -35,7 +35,7 @@
keys = []
- def lookupKeys(self):
+ def _lookupKeys(self):
"""
Do the key lookup using the actual lookup method.
"""
@@ -98,12 +98,6 @@
L{DKIMRequest} support tests.
"""
- def test_valid_request(self):
-
- stream = MemoryStream("")
- request = DKIMRequest("POST", "/", {}, stream, "example.com", "dkim", "/tmp/key", "rsa-sha1", ("Originator", "Recipient",), True, True, 3600)
-
-
@inlineCallbacks
def test_body_hash(self):
@@ -143,7 +137,8 @@
sign_this = """originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com
content-type:%s
-dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=dns/txt:http-well-known; c=relaxed/simple; h=Originator:Recipient; bh=%s; b=
+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)
result = request.generateSignature(sign_this)
@@ -176,8 +171,10 @@
sign_this = """originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com
content-type:%s
-dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=dns/txt:http-well-known; c=relaxed/simple; h=Originator:Recipient:Content-Type; bh=%s; b=
-""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], request.time, request.expire, algorithm, bodyhash)
+ischedule-version:1.0
+ischedule-message-id:%s
+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: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)
@@ -203,15 +200,17 @@
sign_this = """originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com
content-type:%s
-dkim-signature:v=1; d=example.com; s=dkim; t=%s; x=%s; a=%s; q=dns/txt:http-well-known; c=relaxed/simple; h=Originator:Recipient:Content-Type; bh=%s; b=
-""".replace("\n", "\r\n") % (headers.getRawHeaders("Content-Type")[0], request.time, request.expire, algorithm, bodyhash)
+ischedule-version:1.0
+ischedule-message-id:%s
+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: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.PrivateKey.load_pkcs1(open(self.private_keyfile).read())
signature = base64.b64encode(rsa.sign(sign_this, key, hash_name))
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=dns/txt:http-well-known; c=relaxed/simple; h=Originator:Recipient:Content-Type; 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=dns/txt:http/well-known; 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,)
self.assertEqual(request.headers.getRawHeaders("DKIM-Signature")[0], updated_header)
# Try to verify result using public key
@@ -226,7 +225,9 @@
class StubRequest(object):
- def __init__(self, headers, body):
+ 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)
@@ -244,25 +245,28 @@
# More than one
((
- ("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http-well-known; 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; 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; 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"),
), False,),
# Valid
- ((("DKIM-Signature", "v=1; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http-well-known; 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; 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; 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; 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,),
# Invalid
- ((("DKIM-Signature", "v=2; d=example.com; s=dkim; t=1234; a=rsa-sha1; q=dns/txt:http-well-known; 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; 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; 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; c=relaxed/simple; h=Originator:Recipient; bh=abc; b=def"),), False,),
+ ((("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,),
)
for headers, result in data:
- request = self.StubRequest(headers, "")
+ request = self.StubRequest("POST", "/", headers, "")
verifier = DKIMVerifier(request)
if result:
verifier.processDKIMHeader()
@@ -279,20 +283,21 @@
("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"),
+ ("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=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=relaxed/simple; h=Originator:Recipient; bh=abc; b=\r\n",
+ " 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=\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; b= def ; c=relaxed/simple; h=Originator:Recipient; bh=abc",
- "dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; b= ; c=relaxed/simple; h=Originator:Recipient; bh=abc\r\n",
+ " 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\r\n",
),
)
for name, value, result in data:
- request = self.StubRequest(((name, value,),), "")
+ request = self.StubRequest("POST", "/", ((name, value,),), "")
verifier = DKIMVerifier(request)
if name == "DKIM-Signature":
verifier.processDKIMHeader()
@@ -311,14 +316,16 @@
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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=def
+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
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
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=
+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=
"""
),
# Exact count on Recipient
@@ -327,7 +334,8 @@
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
-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=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=def
+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
Cache-Control:no-cache
Connection:close
""",
@@ -335,17 +343,19 @@
originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com , mailto:user03 at example.com
recipient:mailto:user04 at example.com
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=
+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=
"""
),
# 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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; 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; 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
""",
@@ -353,14 +363,16 @@
originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com , mailto:user03 at example.com
recipient:mailto:user04 at example.com
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=
+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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; 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; http=UE9TVDov; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient:iSchedule-Version:iSchedule-Message-ID; bh=abc; b=def
Content-Type: text/calendar ; charset = "utf-8"
Cache-Control:no-cache
Connection:close
@@ -368,14 +380,15 @@
"""content-type:text/calendar ; charset = "utf-8"
originator:mailto:user01 at example.com
recipient:mailto:user02 at example.com , mailto:user03 at example.com
-dkim-signature:v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b=
+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=
"""
),
)
for hdrs, result in data:
headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
- request = self.StubRequest(headers, "")
+ request = self.StubRequest("POST", "/", headers, "")
verifier = DKIMVerifier(request)
verifier.processDKIMHeader()
extracted = verifier.extractSignedHeaders()
@@ -393,7 +406,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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; 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; 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
""",
@@ -405,7 +418,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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; 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; 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
""",
@@ -417,7 +430,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; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; 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; 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
""",
@@ -428,7 +441,7 @@
for hdrs, keys, result in data:
headers = [hdr.split(":", 1) for hdr in hdrs.splitlines()]
- request = self.StubRequest(headers, "")
+ request = self.StubRequest("POST", "/", headers, "")
TestPublicKeyLookup.PublicKeyLookup_Testing.keys = keys
verifier = DKIMVerifier(request, key_lookup=(TestPublicKeyLookup.PublicKeyLookup_Testing,))
verifier.processDKIMHeader()
@@ -621,16 +634,16 @@
(PublicKeyLookup_DNSTXT, "dkim._domainkey.example.com"),
(PublicKeyLookup_HTTP_WellKnown, "https://example.com/.well-known/domainkey/dkim")
):
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
tester = lookup(DKIMUtils.extractTags(dkim))
- self.assertEqual(tester.getSelectorKey(), result)
+ self.assertEqual(tester._getSelectorKey(), result)
@inlineCallbacks
def test_get_key(self):
# Valid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))]
@@ -638,7 +651,7 @@
self.assertNotEqual(pubkey, None)
# Valid with more tags
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k = rsa ; h= sha1 : sha256 ; s=ischedule ; p=%s" % (self.public_key_data,))]
@@ -646,7 +659,7 @@
self.assertNotEqual(pubkey, None)
# Invalid - key type
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=dsa ; p=%s" % (self.public_key_data,))]
@@ -654,7 +667,7 @@
self.assertEqual(pubkey, None)
# Invalid - hash
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; h=sha512 ; p=%s" % (self.public_key_data,))]
@@ -662,7 +675,7 @@
self.assertEqual(pubkey, None)
# Invalid - service
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p=%s" % (self.public_key_data,))]
@@ -670,7 +683,7 @@
self.assertEqual(pubkey, None)
# Invalid - revoked
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; k=rsa ; s=email ; p=")]
@@ -678,7 +691,7 @@
self.assertEqual(pubkey, None)
# Multiple valid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [
@@ -690,7 +703,7 @@
self.assertNotEqual(pubkey, None)
# Multiple - some valid, some invalid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [
@@ -703,7 +716,7 @@
self.assertNotEqual(pubkey, None)
# Multiple - invalid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [
@@ -718,7 +731,7 @@
def test_cached_key(self):
# Create cache entry
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = [DKIMUtils.extractTags("v=DKIM1; p=%s" % (self.public_key_data,))]
@@ -726,14 +739,14 @@
self.assertNotEqual(pubkey, None)
# Cache valid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.keys = []
pubkey = (yield lookup.getPublicKey())
self.assertNotEqual(pubkey, None)
# Cache invalid
- dkim = "v=1; d=example.com; s = dkim; t = 1234; a=rsa-sha1; q=dns/txt:http-well-known ; c=relaxed/simple; h=Content-Type:Originator:Recipient:Recipient; bh=abc; b="
+ dkim = "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="
lookup = TestPublicKeyLookup.PublicKeyLookup_Testing(DKIMUtils.extractTags(dkim))
lookup.flushCache()
lookup.keys = []
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120904/e6e7f78a/attachment-0001.html>
More information about the calendarserver-changes
mailing list