chiark / gitweb /
update: allow deprecated signatures only in the archive
authorHans-Christoph Steiner <hans@eds.org>
Tue, 27 Jun 2017 07:54:35 +0000 (09:54 +0200)
committerHans-Christoph Steiner <hans@eds.org>
Wed, 28 Jun 2017 21:53:42 +0000 (23:53 +0200)
In April 2017, Oracle's jarsigner and Google's apksigner both switched to
considering any APK signature that uses MD5 as unsigned.  Any old build
is likely to have a MD5 signature.  This sets up the archive as the only
place where these "disabled algorithms" are allowed in the repo, and
marks any APK signed by a "disabled algorithm" as having a "known
vulnerability"

This also now automatically moves APKs with invalid signatures to the
archive section.

#323

fdroidserver/common.py
fdroidserver/update.py

index acca01dd104984c761377e54cca96a99b32172e9..884fea4b1763987fbc3478e8ce52d373b3235f7c 100644 (file)
@@ -2041,6 +2041,26 @@ def verify_apk_signature(apk, jar=False):
         return subprocess.call([config['jarsigner'], '-strict', '-verify', apk]) == 4
 
 
+def verify_old_apk_signature(apk):
+    """verify the signature on an archived APK, supporting deprecated algorithms
+
+    F-Droid aims to keep every single binary that it ever published.  Therefore,
+    it needs to be able to verify APK signatures that include deprecated/removed
+    algorithms.  For example, jarsigner treats an MD5 signature as unsigned.
+
+    jarsigner passes unsigned APKs as "verified"! So this has to turn
+    on -strict then check for result 4.
+
+    """
+
+    _java_security = os.path.join(os.getcwd(), '.java.security')
+    with open(_java_security, 'w') as fp:
+        fp.write('jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024')
+
+    return subprocess.call([config['jarsigner'], '-J-Djava.security.properties=' + _java_security,
+                            '-strict', '-verify', apk]) == 4
+
+
 apk_badchars = re.compile('''[/ :;'"]''')
 
 
index 39ab7023f22eda3795126cbbabb04b9bed0d4e2a..6ef9c1269e04c3f06128ff5fb0cb23d3ad0d5044 100644 (file)
@@ -1184,9 +1184,18 @@ def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk):
             apk['srcname'] = srcfilename
         apk['size'] = os.path.getsize(apkfile)
 
-        # verify the jar signature is correct
+        # verify the jar signature is correct, allow deprecated
+        # algorithms only if the APK is in the archive.
         if not common.verify_apk_signature(apkfile):
-            return True, None, False
+            if repodir == 'archive':
+                if common.verify_old_apk_signature(apkfile):
+                    apk['antiFeatures'].add('KnownVuln')
+                else:
+                    return True, None, False
+            else:
+                logging.warning('Archiving "' + apkfilename + '" with invalid signature!')
+                move_apk_between_sections('repo', 'archive', apk)
+                return True, None, False
 
         if has_known_vulnerability(apkfile):
             apk['antiFeatures'].add('KnownVuln')