[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#691698: unblock: dkimpy/0.5.2-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package dkimpy

This upload fixes two grave upstream issues (one of which has
securtyy implicaitions).

unblock dkimpy/0.5.2-1
diff -Nru dkimpy-0.5.2/ChangeLog dkimpy-0.5.3/ChangeLog
--- dkimpy-0.5.2/ChangeLog	2012-06-13 06:27:37.000000000 +0200
+++ dkimpy-0.5.3/ChangeLog	2012-07-21 07:41:31.000000000 +0200
@@ -1,4 +1,8 @@
-2012-06-13 Verion 0.5.2
+UNRELEASED Version 0.5.3
+    - Make key parsing error messages more specific to help troubleshooting
+      (Based on user feedback)
+
+2012-06-13 Version 0.5.2
     - Change canonicalization defaults to work around issues with different
       verification implementations <https://launchpad.net/bugs/939128>
     - Fully fold DKIM-Signature on sign, and ignore FWS in b= value on verify
diff -Nru dkimpy-0.5.2/debian/changelog dkimpy-0.5.3/debian/changelog
--- dkimpy-0.5.2/debian/changelog	2012-10-28 10:48:11.000000000 +0100
+++ dkimpy-0.5.3/debian/changelog	2012-10-28 10:48:12.000000000 +0100
@@ -1,3 +1,15 @@
+dkimpy (0.5.3-1) unstable; urgency=medium
+
+  * Urgency medium for multiple RC bug fixes
+  * New upstream release:
+  * Fix header unfolding and body hash calculation errors that cause
+    correct DKIM signatures to fail to verify in many cases
+    (Closes: #691663)
+  * Add minimum key length requirement to prevent validation of signatures
+    generated with insecure keys (Closes: #691662)
+
+ -- Scott Kitterman <scott@kitterman.com>  Sun, 28 Oct 2012 10:32:13 +0100
+
 dkimpy (0.5.2-1) unstable; urgency=low
 
   * New upstream release
Binary files /tmp/vhfFWHbNtB/dkimpy-0.5.2/dkim/.asn1.py.swp and /tmp/4HMA0c1mG7/dkimpy-0.5.3/dkim/.asn1.py.swp differ
diff -Nru dkimpy-0.5.2/dkim/crypto.py dkimpy-0.5.3/dkim/crypto.py
--- dkimpy-0.5.2/dkim/crypto.py	2012-06-13 06:21:56.000000000 +0200
+++ dkimpy-0.5.3/dkim/crypto.py	2012-07-21 07:39:51.000000000 +0200
@@ -112,7 +112,7 @@
         x = asn1_parse(ASN1_Object, data)
         pkd = asn1_parse(ASN1_RSAPublicKey, x[0][1][1:])
     except ASN1FormatError as e:
-        raise UnparsableKeyError(str(e))
+        raise UnparsableKeyError('Unparsable public key: ' + str(e))
     pk = {
         'modulus': pkd[0][0],
         'publicExponent': pkd[0][1],
@@ -129,7 +129,7 @@
     try:
         pka = asn1_parse(ASN1_RSAPrivateKey, data)
     except ASN1FormatError as e:
-        raise UnparsableKeyError(str(e))
+        raise UnparsableKeyError('Unparsable private key: ' + str(e))
     pk = {
         'version': pka[0][0],
         'modulus': pka[0][1],
diff -Nru dkimpy-0.5.2/dkim/__init__.py dkimpy-0.5.3/dkim/__init__.py
--- dkimpy-0.5.2/dkim/__init__.py	2012-06-13 06:21:56.000000000 +0200
+++ dkimpy-0.5.3/dkim/__init__.py	2012-10-27 18:17:59.000000000 +0200
@@ -65,6 +65,10 @@
 Relaxed = b'relaxed'    # for clients passing dkim.Relaxed
 Simple = b'simple'      # for clients passing dkim.Simple
 
+def bitsize(x):
+    """Return size of long in bits."""
+    return len(bin(x)) - 2
+
 class DKIMException(Exception):
     """Base class for DKIM errors."""
     pass
@@ -114,8 +118,8 @@
         lastindex[h] = i
     return sign_headers
 
-FWS = r'(?:\r\n\s+)?'
-RE_BTAG = re.compile(r'([; ]b'+FWS+r'=)(?:'+FWS+r'[a-zA-Z0-9+/=])*(?:\r\n\Z)?')
+FWS = r'(?:\r?\n\s+)?'
+RE_BTAG = re.compile(r'([;\s]b'+FWS+r'=)(?:'+FWS+r'[a-zA-Z0-9+/=])*(?:\r?\n\Z)?')
 
 def hash_headers(hasher, canonicalize_headers, headers, include_headers,
                  sigheader, sig):
@@ -284,7 +288,8 @@
   #: (with either \\n or \\r\\n line endings)
   #: @param logger: a logger to which debug info will be written (default None)
   #: @param signature_algorithm: the signing algorithm to use when signing
-  def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256'):
+  def __init__(self,message=None,logger=None,signature_algorithm=b'rsa-sha256',
+        minkey=1024):
     self.set_message(message)
     if logger is None:
         logger = get_default_logger()
@@ -302,6 +307,9 @@
     self.should_not_sign = set(DKIM.SHOULD_NOT)
     #: Header fields to sign an extra time to prevent additions.
     self.frozen_sign = set(DKIM.FROZEN)
+    #: Minimum public key size.  Shorter keys raise KeyFormatError. The
+    #: default is 1024
+    self.minkey = minkey
 
   def add_frozen(self,s):
     """ Add headers not in should_not_sign to frozen_sign.
@@ -337,6 +345,8 @@
     #: is a name,value tuple.  FIXME: The headers are canonicalized.
     #: This could be more useful as original headers.
     self.signed_headers = []
+    #: The public key size last verified.
+    self.keysize = 0
 
   def default_sign_headers(self):
     """Return the default list of headers to sign: those in should_sign or
@@ -493,6 +503,8 @@
     logger.debug("sig: %r" % sig)
 
     validate_signature_fields(sig)
+    self.domain = sig[b'd']
+    self.selector = sig[b's']
 
     try:
         canon_policy = CanonicalizationPolicy.from_c_value(sig.get(b'c'))
@@ -506,8 +518,6 @@
     except KeyError as e:
         raise MessageFormatError("unknown signature algorithm: %s" % e.args[0])
 
-    self.domain = sig[b'd']
-    self.selector = sig[b's']
     if b'l' in sig:
         body = body[:int(sig[b'l'])]
 
@@ -534,6 +544,7 @@
         raise KeyFormatError(e)
     try:
         pk = parse_public_key(base64.b64decode(pub[b'p']))
+        self.keysize = bitsize(pk['modulus'])
     except KeyError:
         raise KeyFormatError("incomplete public key: %s" % s)
     except (TypeError,UnparsableKeyError) as e:
@@ -551,7 +562,10 @@
         h, canon_policy, headers, include_headers, sigheaders[idx], sig)
     try:
         signature = base64.b64decode(re.sub(br"\s+", b"", sig[b'b']))
-        return RSASSA_PKCS1_v1_5_verify(h, signature, pk)
+        res = RSASSA_PKCS1_v1_5_verify(h, signature, pk)
+        if res and self.keysize < self.minkey:
+          raise KeyFormatError("public key too small: %d" % self.keysize)
+        return res
     except (TypeError,DigestTooLargeError) as e:
         raise KeyFormatError("digest too large for modulus: %s"%e)
 
@@ -578,13 +592,13 @@
         include_headers = d.all_sign_headers()
     return d.sign(selector, domain, privkey, identity=identity, canonicalize=canonicalize, include_headers=include_headers, length=length)
 
-def verify(message, logger=None, dnsfunc=get_txt):
+def verify(message, logger=None, dnsfunc=get_txt, minkey=1024):
     """Verify the first (topmost) DKIM signature on an RFC822 formatted message.
     @param message: an RFC822 formatted message (with either \\n or \\r\\n line endings)
     @param logger: a logger to which debug info will be written (default None)
     @return: True if signature verifies or False otherwise
     """
-    d = DKIM(message,logger=logger)
+    d = DKIM(message,logger=logger,minkey=minkey)
     try:
         return d.verify(dnsfunc=dnsfunc)
     except DKIMException as x:
diff -Nru dkimpy-0.5.2/dkim/tests/test_dkim.py dkimpy-0.5.3/dkim/tests/test_dkim.py
--- dkimpy-0.5.2/dkim/tests/test_dkim.py	2012-06-13 06:21:56.000000000 +0200
+++ dkimpy-0.5.3/dkim/tests/test_dkim.py	2012-10-27 18:17:59.000000000 +0200
@@ -135,7 +135,15 @@
         # simple canonicalization.  
         # http://tools.ietf.org/html/rfc4871#section-3.5
         signed = dkim.fold(dkim_header) + sample_msg
-        result = dkim.verify(signed,dnsfunc=lambda x: _dns_responses[x])
+        result = dkim.verify(signed,dnsfunc=lambda x: _dns_responses[x],
+                minkey=512)
+        self.assertTrue(result)
+        dkim_header = dkim.fold(dkim_header)
+        # use a tab for last fold to test tab in FWS bug
+        pos = dkim_header.rindex(b'\r\n ')
+        dkim_header = dkim_header[:pos]+b'\r\n\t'+dkim_header[pos+3:]
+        result = dkim.verify(dkim_header + sample_msg,
+                dnsfunc=lambda x: _dns_responses[x], minkey=512)
         self.assertTrue(result)
 
     def test_extra_headers(self):
diff -Nru dkimpy-0.5.2/PKG-INFO dkimpy-0.5.3/PKG-INFO
--- dkimpy-0.5.2/PKG-INFO	2012-06-13 06:59:38.000000000 +0200
+++ dkimpy-0.5.3/PKG-INFO	2012-10-27 18:21:31.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: dkimpy
-Version: 0.5.2
+Version: 0.5.3
 Summary: DKIM (DomainKeys Identified Mail)
 Home-page: https://launchpad.net/dkimpy
 Author: Scott Kitterman
diff -Nru dkimpy-0.5.2/README dkimpy-0.5.3/README
--- dkimpy-0.5.2/README	2012-06-13 06:23:07.000000000 +0200
+++ dkimpy-0.5.3/README	2012-07-21 07:43:06.000000000 +0200
@@ -11,7 +11,7 @@
 
 VERSION
 
-This is dkimpy 0.5.2.
+This is dkimpy 0.5.3.
 
 REQUIREMENTS
 
diff -Nru dkimpy-0.5.2/setup.py dkimpy-0.5.3/setup.py
--- dkimpy-0.5.2/setup.py	2012-06-13 06:58:48.000000000 +0200
+++ dkimpy-0.5.3/setup.py	2012-07-21 07:41:46.000000000 +0200
@@ -24,7 +24,7 @@
 from distutils.core import setup
 import os
 
-version = "0.5.2"
+version = "0.5.3"
 
 setup(
     name = "dkimpy",

Reply to: