diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 571253af..d0e173d8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,6 +2,7 @@ image: registry.gitlab.com/fdroid/ci-images:server-latest test: script: + - apt-get -qq update && apt-get -y dist-upgrade - mkdir -p /usr/lib/python3.4/site-packages/ # workaround https://github.com/pypa/setuptools/issues/937 - pip3 install setuptools==33.1.1 diff --git a/examples/config.py b/examples/config.py index 0a0558b3..974f8ee1 100644 --- a/examples/config.py +++ b/examples/config.py @@ -71,6 +71,15 @@ archive_description = """ The repository of older versions of applications from the main demo repository. """ +# This allows a specific kind of insecure APK to be included in the +# 'repo' section. Since April 2017, APK signatures that use MD5 are +# no longer considered valid, jarsigner and apksigner will return an +# error when verifying. `fdroid update` will move APKs with these +# disabled signatures to the archive. This option stops that +# behavior, and lets those APKs stay part of 'repo'. +# +# allow_disabled_algorithms = True + # Normally, all apps are collected into a single app repository, like on # https://f-droid.org. For certain situations, it is better to make a repo # that is made up of APKs only from a single app. For example, an automated diff --git a/fdroidserver/common.py b/fdroidserver/common.py index acca01dd..76888cce 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -85,6 +85,7 @@ default_config = { 'gradle': 'gradle', 'accepted_formats': ['txt', 'yml'], 'sync_from_local_copy_dir': False, + 'allow_disabled_algorithms': False, 'per_app_repos': False, 'make_current_version_link': True, 'current_version_name_source': 'Name', @@ -2041,6 +2042,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('''[/ :;'"]''') diff --git a/fdroidserver/update.py b/fdroidserver/update.py index 1f322837..6e77d88c 100644 --- a/fdroidserver/update.py +++ b/fdroidserver/update.py @@ -423,20 +423,35 @@ def get_cache_file(): def get_cache(): - """ + """Get the cached dict of the APK index + Gather information about all the apk files in the repo directory, - using cached data if possible. + using cached data if possible. Some of the index operations take a + long time, like calculating the SHA-256 and verifying the APK + signature. + + The cache is invalidated if the metadata version is different, or + the 'allow_disabled_algorithms' config/option is different. In + those cases, there is no easy way to know what has changed from + the cache, so just rerun the whole thing. + :return: apkcache + """ apkcachefile = get_cache_file() + ada = options.allow_disabled_algorithms or config['allow_disabled_algorithms'] if not options.clean and os.path.exists(apkcachefile): with open(apkcachefile, 'rb') as cf: apkcache = pickle.load(cf, encoding='utf-8') - if apkcache.get("METADATA_VERSION") != METADATA_VERSION: + if apkcache.get("METADATA_VERSION") != METADATA_VERSION \ + or apkcache.get('allow_disabled_algorithms') != ada: apkcache = {} else: apkcache = {} + apkcache["METADATA_VERSION"] = METADATA_VERSION + apkcache['allow_disabled_algorithms'] = ada + return apkcache @@ -445,7 +460,6 @@ def write_cache(apkcache): cache_path = os.path.dirname(apkcachefile) if not os.path.exists(cache_path): os.makedirs(cache_path) - apkcache["METADATA_VERSION"] = METADATA_VERSION with open(apkcachefile, 'wb') as cf: pickle.dump(apkcache, cf) @@ -1082,7 +1096,8 @@ def scan_apk_androguard(apk, apkfile): apk['features'].append(feature) -def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk): +def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk=False, + allow_disabled_algorithms=False, archive_bad_sig=False): """Scan the apk with the given filename in the given repo directory. This also extracts the icons. @@ -1093,6 +1108,9 @@ def scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk): :param knownapks: known apks info :param use_date_from_apk: use date from APK (instead of current date) for newly added APKs + :param allow_disabled_algorithms: allow APKs with valid signatures that include + disabled algorithms in the signature (e.g. MD5) + :param archive_bad_sig: move APKs with a bad signature to the archive :returns: (skip, apk, cachechanged) where skip is a boolean indicating whether to skip this apk, apk is the scanned apk information, and cachechanged is True if the apkcache got changed. """ @@ -1184,12 +1202,29 @@ 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. + skipapk = False if not common.verify_apk_signature(apkfile): + if repodir == 'archive' or allow_disabled_algorithms: + if common.verify_old_apk_signature(apkfile): + apk['antiFeatures'].update(['KnownVuln', 'DisabledAlgorithm']) + else: + skipapk = True + else: + skipapk = True + + if skipapk: + if archive_bad_sig: + logging.warning('Archiving "' + apkfilename + '" with invalid signature!') + move_apk_between_sections(repodir, 'archive', apk) + else: + logging.warning('Skipping "' + apkfilename + '" with invalid signature!') return True, None, False - if has_known_vulnerability(apkfile): - apk['antiFeatures'].add('KnownVuln') + if 'KnownVuln' not in apk['antiFeatures']: + if has_known_vulnerability(apkfile): + apk['antiFeatures'].add('KnownVuln') apkzip = zipfile.ZipFile(apkfile, 'r') @@ -1363,10 +1398,13 @@ def scan_apks(apkcache, repodir, knownapks, use_date_from_apk=False): apks = [] for apkfile in sorted(glob.glob(os.path.join(repodir, '*.apk'))): apkfilename = apkfile[len(repodir) + 1:] - (skip, apk, cachechanged) = scan_apk(apkcache, apkfilename, repodir, knownapks, use_date_from_apk) + ada = options.allow_disabled_algorithms or config['allow_disabled_algorithms'] + (skip, apk, cachethis) = scan_apk(apkcache, apkfilename, repodir, knownapks, + use_date_from_apk, ada, True) if skip: continue apks.append(apk) + cachechanged = cachechanged or cachethis return apks, cachechanged @@ -1421,6 +1459,15 @@ def make_categories_txt(repodir, categories): def archive_old_apks(apps, apks, archapks, repodir, archivedir, defaultkeepversions): + def filter_apk_list_sorted(apk_list): + res = [] + for apk in apk_list: + if apk['packageName'] == appid: + res.append(apk) + + # Sort the apk list by version code. First is highest/newest. + return sorted(res, key=lambda apk: apk['versionCode'], reverse=True) + for appid, app in apps.items(): if app.ArchivePolicy: @@ -1428,60 +1475,57 @@ def archive_old_apks(apps, apks, archapks, repodir, archivedir, defaultkeepversi else: keepversions = defaultkeepversions - def filter_apk_list_sorted(apk_list): - res = [] - for apk in apk_list: - if apk['packageName'] == appid: - res.append(apk) - - # Sort the apk list by version code. First is highest/newest. - return sorted(res, key=lambda apk: apk['versionCode'], reverse=True) - - def move_file(from_dir, to_dir, filename, ignore_missing): - from_path = os.path.join(from_dir, filename) - if ignore_missing and not os.path.exists(from_path): - return - to_path = os.path.join(to_dir, filename) - shutil.move(from_path, to_path) - logging.debug("Checking archiving for {0} - apks:{1}, keepversions:{2}, archapks:{3}" .format(appid, len(apks), keepversions, len(archapks))) - if len(apks) > keepversions: - apklist = filter_apk_list_sorted(apks) + current_app_apks = filter_apk_list_sorted(apks) + if len(current_app_apks) > keepversions: # Move back the ones we don't want. - for apk in apklist[keepversions:]: - logging.info("Moving " + apk['apkName'] + " to archive") - move_file(repodir, archivedir, apk['apkName'], False) - move_file(repodir, archivedir, apk['apkName'] + '.asc', True) - for density in all_screen_densities: - repo_icon_dir = get_icon_dir(repodir, density) - archive_icon_dir = get_icon_dir(archivedir, density) - if density not in apk['icons']: - continue - move_file(repo_icon_dir, archive_icon_dir, apk['icons'][density], True) - if 'srcname' in apk: - move_file(repodir, archivedir, apk['srcname'], False) + for apk in current_app_apks[keepversions:]: + move_apk_between_sections(repodir, archivedir, apk) archapks.append(apk) apks.remove(apk) - elif len(apks) < keepversions and len(archapks) > 0: - required = keepversions - len(apks) - archapklist = filter_apk_list_sorted(archapks) - # Move forward the ones we want again. - for apk in archapklist[:required]: - logging.info("Moving " + apk['apkName'] + " from archive") - move_file(archivedir, repodir, apk['apkName'], False) - move_file(archivedir, repodir, apk['apkName'] + '.asc', True) - for density in all_screen_densities: - repo_icon_dir = get_icon_dir(repodir, density) - archive_icon_dir = get_icon_dir(archivedir, density) - if density not in apk['icons']: - continue - move_file(archive_icon_dir, repo_icon_dir, apk['icons'][density], True) - if 'srcname' in apk: - move_file(archivedir, repodir, apk['srcname'], False) - archapks.remove(apk) - apks.append(apk) + + current_app_archapks = filter_apk_list_sorted(archapks) + if len(current_app_apks) < keepversions and len(current_app_archapks) > 0: + kept = 0 + # Move forward the ones we want again, except DisableAlgorithm + for apk in current_app_archapks: + if 'DisabledAlgorithm' not in apk['antiFeatures']: + move_apk_between_sections(archivedir, repodir, apk) + archapks.remove(apk) + apks.append(apk) + kept += 1 + if kept == keepversions: + break + + +def move_apk_between_sections(from_dir, to_dir, apk): + """move an APK from repo to archive or vice versa""" + + def _move_file(from_dir, to_dir, filename, ignore_missing): + from_path = os.path.join(from_dir, filename) + if ignore_missing and not os.path.exists(from_path): + return + to_path = os.path.join(to_dir, filename) + if not os.path.exists(to_dir): + os.mkdir(to_dir) + shutil.move(from_path, to_path) + + if from_dir == to_dir: + return + + logging.info("Moving %s from %s to %s" % (apk['apkName'], from_dir, to_dir)) + _move_file(from_dir, to_dir, apk['apkName'], False) + _move_file(from_dir, to_dir, apk['apkName'] + '.asc', True) + for density in all_screen_densities: + from_icon_dir = get_icon_dir(from_dir, density) + to_icon_dir = get_icon_dir(to_dir, density) + if density not in apk['icons']: + continue + _move_file(from_icon_dir, to_icon_dir, apk['icons'][density], True) + if 'srcname' in apk: + _move_file(from_dir, to_dir, apk['srcname'], False) def add_apks_to_per_app_repos(repodir, apks): @@ -1544,6 +1588,8 @@ def main(): help="Use date from apk instead of current time for newly added apks") parser.add_argument("--rename-apks", action="store_true", default=False, help="Rename APK files that do not match package.name_123.apk") + parser.add_argument("--allow-disabled-algorithms", action="store_true", default=False, + help="Include APKs that are signed with disabled algorithms like MD5") metadata.add_metadata_arguments(parser) options = parser.parse_args() metadata.warnings_action = options.W diff --git a/tests/metadata/com.politedroid.txt b/tests/metadata/com.politedroid.txt new file mode 100644 index 00000000..526be787 --- /dev/null +++ b/tests/metadata/com.politedroid.txt @@ -0,0 +1,36 @@ +Categories:Time +License:GPL-3.0 +Web Site: +Source Code:https://github.com/miguelvps/PoliteDroid +Issue Tracker:https://github.com/miguelvps/PoliteDroid/issues + +Auto Name:Polite Droid +Summary:Calendar tool +Description: +Activates silent mode during calendar events. +. + +Repo Type:git +Repo:https://github.com/miguelvps/PoliteDroid.git + +Build:1.2,3 + commit=6a548e4b19 + target=android-10 + +Build:1.3,4 + commit=ad865b57bf3ac59580f38485608a9b1dda4fa7dc + target=android-15 + +Build:1.4,5 + commit=456bd615f3fbe6dff06433928cf7ea20073601fb + target=android-10 + +Build:1.5,6 + commit=v1.5 + gradle=yes + +Archive Policy:4 versions +Auto Update Mode:Version v%v +Update Check Mode:Tags +Current Version:1.5 +Current Version Code:6 diff --git a/tests/org.bitbucket.tickytacky.mirrormirror_1.apk b/tests/org.bitbucket.tickytacky.mirrormirror_1.apk new file mode 100644 index 00000000..6ec4272f Binary files /dev/null and b/tests/org.bitbucket.tickytacky.mirrormirror_1.apk differ diff --git a/tests/org.bitbucket.tickytacky.mirrormirror_2.apk b/tests/org.bitbucket.tickytacky.mirrormirror_2.apk new file mode 100644 index 00000000..26474277 Binary files /dev/null and b/tests/org.bitbucket.tickytacky.mirrormirror_2.apk differ diff --git a/tests/org.bitbucket.tickytacky.mirrormirror_3.apk b/tests/org.bitbucket.tickytacky.mirrormirror_3.apk new file mode 100644 index 00000000..af2a1fe8 Binary files /dev/null and b/tests/org.bitbucket.tickytacky.mirrormirror_3.apk differ diff --git a/tests/org.bitbucket.tickytacky.mirrormirror_4.apk b/tests/org.bitbucket.tickytacky.mirrormirror_4.apk new file mode 100644 index 00000000..a5f52eda Binary files /dev/null and b/tests/org.bitbucket.tickytacky.mirrormirror_4.apk differ diff --git a/tests/repo/categories.txt b/tests/repo/categories.txt index a4664e81..d4a50083 100644 --- a/tests/repo/categories.txt +++ b/tests/repo/categories.txt @@ -7,3 +7,4 @@ None Phone & SMS Security System +Time diff --git a/tests/repo/com.politedroid_3.apk b/tests/repo/com.politedroid_3.apk new file mode 100644 index 00000000..19634ba9 Binary files /dev/null and b/tests/repo/com.politedroid_3.apk differ diff --git a/tests/repo/com.politedroid_4.apk b/tests/repo/com.politedroid_4.apk new file mode 100644 index 00000000..7ef46599 Binary files /dev/null and b/tests/repo/com.politedroid_4.apk differ diff --git a/tests/repo/com.politedroid_5.apk b/tests/repo/com.politedroid_5.apk new file mode 100644 index 00000000..35e0ed6c Binary files /dev/null and b/tests/repo/com.politedroid_5.apk differ diff --git a/tests/repo/com.politedroid_6.apk b/tests/repo/com.politedroid_6.apk new file mode 100644 index 00000000..f48d8082 Binary files /dev/null and b/tests/repo/com.politedroid_6.apk differ diff --git a/tests/repo/index.xml b/tests/repo/index.xml index 4b85a960..9836fc3e 100644 --- a/tests/repo/index.xml +++ b/tests/repo/index.xml @@ -159,6 +159,71 @@ b4964fd759edaa54e65bb476d0276880 + + com.politedroid + 2017-06-23 + 2017-06-23 + Polite Droid + Calendar tool + com.politedroid.6.png + <p>Activates silent mode during calendar events.</p> + GPL-3.0 + Time + Time + + https://github.com/miguelvps/PoliteDroid + https://github.com/miguelvps/PoliteDroid/issues + 1.5 + 6 + + 1.5 + 6 + com.politedroid_6.apk + 70c2f776a2bac38a58a7d521f96ee0414c6f0fb1de973c3ca8b10862a009247d + 16578 + 14 + 21 + 2017-06-23 + b4964fd759edaa54e65bb476d0276880 + READ_CALENDAR,RECEIVE_BOOT_COMPLETED + + + 1.4 + 5 + com.politedroid_5.apk + 5bdbfa071cca4b8d05ced41d6b28763595d6e8096cca5bbf0f9253c9a2622e5d + 18817 + 3 + 10 + 2017-06-23 + b4964fd759edaa54e65bb476d0276880 + READ_CALENDAR,RECEIVE_BOOT_COMPLETED + + + 1.3 + 4 + com.politedroid_4.apk + c809bdff83715fbf919f3840ee09869b038e209378b906e135ee40d3f0e1f075 + 18489 + 3 + 3 + 2017-06-23 + b4964fd759edaa54e65bb476d0276880 + READ_CALENDAR,READ_EXTERNAL_STORAGE,READ_PHONE_STATE,RECEIVE_BOOT_COMPLETED,WRITE_EXTERNAL_STORAGE + + + 1.2 + 3 + com.politedroid_3.apk + 665d03d61ebc642289fda697f71a59305b0202b16cafc5ffdae91cbe91f0b25d + 17552 + 3 + 3 + 2017-06-23 + b4964fd759edaa54e65bb476d0276880 + READ_CALENDAR,READ_EXTERNAL_STORAGE,READ_PHONE_STATE,RECEIVE_BOOT_COMPLETED,WRITE_EXTERNAL_STORAGE + + info.guardianproject.urzip 2016-06-23 diff --git a/tests/run-tests b/tests/run-tests index a3d62d27..625402e8 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -141,6 +141,8 @@ $fdroid signindex --verbose test -e repo/index.xml test -e repo/index.jar test -e repo/index-v1.jar +test -e tmp/apkcache +! test -z tmp/apkcache test -L urzip.apk grep -F '> config.py +echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo "accepted_formats = ['txt']" >> config.py +sed -i '/allow_disabled_algorithms/d' config.py +test -d metadata || mkdir metadata +cp $WORKSPACE/tests/metadata/*.txt metadata/ +echo 'Summary:good test version of urzip' > metadata/info.guardianproject.urzip.txt +echo 'Summary:good MD5 sig, which is disabled algorithm' > metadata/org.bitbucket.tickytacky.mirrormirror.txt +sed -i '/Archive Policy:/d' metadata/*.txt +test -d repo || mkdir repo +cp $WORKSPACE/tests/urzip.apk \ + $WORKSPACE/tests/org.bitbucket.tickytacky.mirrormirror_[0-9].apk \ + $WORKSPACE/tests/repo/com.politedroid_[0-9].apk \ + $WORKSPACE/tests/repo/obb.main.twoversions_110161[357].apk \ + repo/ +sed -i 's,archive_older = [0-9],archive_older = 3,' config.py + +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 5 +test `grep '' repo/index.xml | wc -l` -eq 7 + + +#------------------------------------------------------------------------------# +echo_header 'test per-app "Archive Policy"' + +REPOROOT=`create_test_dir` +cd $REPOROOT +cp $WORKSPACE/tests/keystore.jks $REPOROOT/ +$fdroid init --keystore keystore.jks --repo-keyalias=sova +echo 'keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo "accepted_formats = ['txt']" >> config.py +test -d metadata || mkdir metadata +cp $WORKSPACE/tests/metadata/com.politedroid.txt metadata/ +test -d repo || mkdir repo +cp $WORKSPACE/tests/repo/com.politedroid_[0-9].apk repo/ +sed -i 's,archive_older = [0-9],archive_older = 3,' config.py + +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 0 +test `grep '' repo/index.xml | wc -l` -eq 4 +grep -F com.politedroid_3.apk repo/index.xml +grep -F com.politedroid_4.apk repo/index.xml +grep -F com.politedroid_5.apk repo/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e repo/com.politedroid_3.apk +test -e repo/com.politedroid_4.apk +test -e repo/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk + +echo "enable one app in the repo" +sed -i 's,^Archive Policy:4,Archive Policy:1,' metadata/com.politedroid.txt +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 3 +test `grep '' repo/index.xml | wc -l` -eq 1 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk archive/index.xml +grep -F com.politedroid_5.apk archive/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +test -e archive/com.politedroid_4.apk +test -e archive/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk + +echo "remove all apps from the repo" +sed -i 's,^Archive Policy:1,Archive Policy:0,' metadata/com.politedroid.txt +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 4 +test `grep '' repo/index.xml | wc -l` -eq 0 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk archive/index.xml +grep -F com.politedroid_5.apk archive/index.xml +grep -F com.politedroid_6.apk archive/index.xml +test -e archive/com.politedroid_3.apk +test -e archive/com.politedroid_4.apk +test -e archive/com.politedroid_5.apk +test -e archive/com.politedroid_6.apk +! test -e repo/com.politedroid_6.apk + +echo "move back one from archive to the repo" +sed -i 's,^Archive Policy:0,Archive Policy:1,' metadata/com.politedroid.txt +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 3 +test `grep '' repo/index.xml | wc -l` -eq 1 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk archive/index.xml +grep -F com.politedroid_5.apk archive/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +test -e archive/com.politedroid_4.apk +test -e archive/com.politedroid_5.apk +! test -e archive/com.politedroid_6.apk +test -e repo/com.politedroid_6.apk + + + +#------------------------------------------------------------------------------# +echo_header 'test moving old APKs to and from the archive' + +REPOROOT=`create_test_dir` +cd $REPOROOT +cp $WORKSPACE/tests/keystore.jks $REPOROOT/ +$fdroid init --keystore keystore.jks --repo-keyalias=sova +echo 'keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo "accepted_formats = ['txt']" >> config.py +test -d metadata || mkdir metadata +cp $WORKSPACE/tests/metadata/com.politedroid.txt metadata/ +sed -i '/Archive Policy:/d' metadata/com.politedroid.txt +test -d repo || mkdir repo +cp $WORKSPACE/tests/repo/com.politedroid_[0-9].apk repo/ +sed -i 's,archive_older = [0-9],archive_older = 3,' config.py + +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 1 +test `grep '' repo/index.xml | wc -l` -eq 3 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk repo/index.xml +grep -F com.politedroid_5.apk repo/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +test -e repo/com.politedroid_4.apk +test -e repo/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk + +sed -i 's,archive_older = 3,archive_older = 1,' config.py +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 3 +test `grep '' repo/index.xml | wc -l` -eq 1 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk archive/index.xml +grep -F com.politedroid_5.apk archive/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +test -e archive/com.politedroid_4.apk +test -e archive/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk + +# disabling deletes from the archive +sed -i 's/Build:1.3,4/Build:1.3,4\n disable=testing deletion/' metadata/com.politedroid.txt +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 2 +test `grep '' repo/index.xml | wc -l` -eq 1 +grep -F com.politedroid_3.apk archive/index.xml +! grep -F com.politedroid_4.apk archive/index.xml +grep -F com.politedroid_5.apk archive/index.xml +grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +! test -e archive/com.politedroid_4.apk +test -e archive/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk + +# disabling deletes from the repo, and promotes one from the archive +sed -i 's/Build:1.5,6/Build:1.5,6\n disable=testing deletion/' metadata/com.politedroid.txt +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 1 +test `grep '' repo/index.xml | wc -l` -eq 1 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_5.apk repo/index.xml +! grep -F com.politedroid_6.apk repo/index.xml +test -e archive/com.politedroid_3.apk +test -e repo/com.politedroid_5.apk +! test -e repo/com.politedroid_6.apk + + +#------------------------------------------------------------------------------# +echo_header 'test allowing disabled signatures in repo and archive' + +REPOROOT=`create_test_dir` +cd $REPOROOT +cp $WORKSPACE/tests/keystore.jks $REPOROOT/ +$fdroid init --keystore keystore.jks --repo-keyalias=sova +echo 'keystorepass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo 'keypass = "r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI="' >> config.py +echo "accepted_formats = ['txt']" >> config.py +echo 'allow_disabled_algorithms = True' >> config.py +sed -i 's,archive_older = [0-9],archive_older = 3,' config.py +test -d metadata || mkdir metadata +cp $WORKSPACE/tests/metadata/com.politedroid.txt metadata/ +echo 'Summary:good test version of urzip' > metadata/info.guardianproject.urzip.txt +echo 'Summary:good MD5 sig, disabled algorithm' > metadata/org.bitbucket.tickytacky.mirrormirror.txt +sed -i '/Archive Policy:/d' metadata/*.txt +test -d repo || mkdir repo +cp $WORKSPACE/tests/repo/com.politedroid_[0-9].apk \ + $WORKSPACE/tests/org.bitbucket.tickytacky.mirrormirror_[0-9].apk \ + $WORKSPACE/tests/urzip-badsig.apk \ + repo/ + +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 2 +test `grep '' repo/index.xml | wc -l` -eq 6 +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk repo/index.xml +grep -F com.politedroid_5.apk repo/index.xml +grep -F com.politedroid_6.apk repo/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_1.apk archive/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_2.apk repo/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_3.apk repo/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_4.apk repo/index.xml +! grep -F urzip-badsig.apk repo/index.xml +! grep -F urzip-badsig.apk archive/index.xml +test -e archive/com.politedroid_3.apk +test -e repo/com.politedroid_4.apk +test -e repo/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk +test -e archive/org.bitbucket.tickytacky.mirrormirror_1.apk +test -e repo/org.bitbucket.tickytacky.mirrormirror_2.apk +test -e repo/org.bitbucket.tickytacky.mirrormirror_3.apk +test -e repo/org.bitbucket.tickytacky.mirrormirror_4.apk +test -e archive/urzip-badsig.apk + +sed -i '/allow_disabled_algorithms/d' config.py +$fdroid update --pretty --nosign +test `grep '' archive/index.xml | wc -l` -eq 5 +test `grep '' repo/index.xml | wc -l` -eq 3 +grep -F org.bitbucket.tickytacky.mirrormirror_1.apk archive/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_2.apk archive/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_3.apk archive/index.xml +grep -F org.bitbucket.tickytacky.mirrormirror_4.apk archive/index.xml +grep -F com.politedroid_3.apk archive/index.xml +grep -F com.politedroid_4.apk repo/index.xml +grep -F com.politedroid_5.apk repo/index.xml +grep -F com.politedroid_6.apk repo/index.xml +! grep -F urzip-badsig.apk repo/index.xml +! grep -F urzip-badsig.apk archive/index.xml +test -e archive/org.bitbucket.tickytacky.mirrormirror_1.apk +test -e archive/org.bitbucket.tickytacky.mirrormirror_2.apk +test -e archive/org.bitbucket.tickytacky.mirrormirror_3.apk +test -e archive/org.bitbucket.tickytacky.mirrormirror_4.apk +test -e archive/com.politedroid_3.apk +test -e archive/urzip-badsig.apk +test -e repo/com.politedroid_4.apk +test -e repo/com.politedroid_5.apk +test -e repo/com.politedroid_6.apk #------------------------------------------------------------------------------# @@ -517,6 +762,8 @@ grep -F '