Fix #263 "cannot manually add repo that was swapped before"

Pretends that the swap repo never existed, by deleting it before adding
the new repo, and showing the same message that is shown when a new
repo is added. This does not change behaviour for existing non-swap
repos. They are not deleted before being added again, or else we would
lose the ability to verify the fingerprint of an existing repo is the
same as a newly added one with the same URL.

Note that this has the effect that the fingerprint/pubkey of the swap
repo is nuked when adding that repo manually.

Internationalised the string "BAD FINGERPRINT" while I was at it.
This commit is contained in:
Peter Serwylo 2015-05-19 22:42:45 +10:00
父節點 cbf59f9dd0
當前提交 5065c37e13
共有 6 個文件被更改,包括 43 次插入27 次删除

查看文件

@ -97,6 +97,7 @@
<string name="repo_exists_enable">This repo is already setup, confirm that you want to re-enable it.</string>
<string name="repo_exists_and_enabled">The incoming repo is already setup and enabled.</string>
<string name="repo_delete_to_overwrite">You must first delete this repo before you can add one with a different key.</string>
<string name="bad_fingerprint">BAD FINGERPRINT</string>
<string name="invalid_url">This is not a valid URL.</string>
<string name="malformed_repo_uri">Ignoring malformed repo URI: %s</string>

查看文件

@ -21,6 +21,7 @@ package org.fdroid.fdroid;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.support.annotation.NonNull;
@ -281,11 +282,11 @@ public final class Utils {
}
// return a fingerprint formatted for display
public static String formatFingerprint(String fingerprint) {
public static String formatFingerprint(Context context, String fingerprint) {
if (TextUtils.isEmpty(fingerprint)
|| fingerprint.length() != 64 // SHA-256 is 64 hex chars
|| fingerprint.matches(".*[^0-9a-fA-F].*")) // its a hex string
return "BAD FINGERPRINT";
return context.getString(R.string.bad_fingerprint);
String displayFP = fingerprint.substring(0, 2);
for (int i = 2; i < fingerprint.length(); i = i + 2)
displayFP += " " + fingerprint.substring(i, i + 2);

查看文件

@ -100,7 +100,8 @@ public class ManageReposActivity extends ActionBarActivity {
private enum AddRepoState {
DOESNT_EXIST, EXISTS_FINGERPRINT_MISMATCH, EXISTS_FINGERPRINT_MATCH,
EXISTS_DISABLED, EXISTS_ENABLED, EXISTS_UPGRADABLE_TO_SIGNED, INVALID_URL
EXISTS_DISABLED, EXISTS_ENABLED, EXISTS_UPGRADABLE_TO_SIGNED, INVALID_URL,
IS_SWAP
}
private UpdateService.UpdateReceiver updateHandler = null;
@ -404,6 +405,13 @@ public class ManageReposActivity extends ActionBarActivity {
prepareToCreateNewRepo(url, fp);
break;
case IS_SWAP:
Log.i(TAG, "Removing existing swap repo " + url + " before adding new repo.");
Repo repo = RepoProvider.Helper.findByAddress(context, url);
RepoProvider.Helper.remove(context, repo.getId());
prepareToCreateNewRepo(url, fp);
break;
case EXISTS_DISABLED:
case EXISTS_UPGRADABLE_TO_SIGNED:
case EXISTS_FINGERPRINT_MATCH:
@ -473,7 +481,9 @@ public class ManageReposActivity extends ActionBarActivity {
if (repo == null) {
repoDoesntExist();
} else {
if (repo.fingerprint == null && fingerprint.length() > 0) {
if (repo.isSwap) {
repoIsSwap();
} else if (repo.fingerprint == null && fingerprint.length() > 0) {
upgradingToSigned();
} else if (repo.fingerprint != null && !repo.fingerprint.equalsIgnoreCase(fingerprint)) {
repoFingerprintDoesntMatch();
@ -493,6 +503,10 @@ public class ManageReposActivity extends ActionBarActivity {
updateUi(AddRepoState.DOESNT_EXIST, 0, false, R.string.repo_add_add, true);
}
private void repoIsSwap() {
updateUi(AddRepoState.IS_SWAP, 0, false, R.string.repo_add_add, true);
}
/**
* Same address with different fingerprint, this could be malicious, so display a message
* force the user to manually delete the repo before adding this one.
@ -654,6 +668,11 @@ public class ManageReposActivity extends ActionBarActivity {
}
private void createNewRepo(String address, String fingerprint) {
try {
address = normalizeUrl(address);
} catch (URISyntaxException e) {
// Leave address as it was.
}
ContentValues values = new ContentValues(2);
values.put(RepoProvider.DataColumns.ADDRESS, address);
if (fingerprint != null && fingerprint.length() > 0) {

查看文件

@ -366,7 +366,7 @@ public class RepoDetailsFragment extends Fragment {
String repoFingerprint;
int repoFingerprintColor;
// TODO show the current state of the signature check, not just whether there is a key or not
// TODO show the current state of the signature check, not just whether there is a key or not
if (TextUtils.isEmpty(repo.fingerprint) && TextUtils.isEmpty(repo.pubkey)) {
repoFingerprint = getResources().getString(R.string.unsigned);
repoFingerprintColor = getResources().getColor(R.color.unsigned);
@ -374,7 +374,7 @@ public class RepoDetailsFragment extends Fragment {
repoFingerprintDescView.setText(getResources().getString(R.string.unsigned_description));
} else {
// this is based on repo.fingerprint always existing, which it should
repoFingerprint = Utils.formatFingerprint(repo.fingerprint);
repoFingerprint = Utils.formatFingerprint(getActivity(), repo.fingerprint);
repoFingerprintColor = getResources().getColor(R.color.signed);
repoFingerprintDescView.setVisibility(View.GONE);
}

查看文件

@ -149,11 +149,6 @@ public class ConnectSwapActivity extends ActionBarActivity implements ProgressLi
values.put(RepoProvider.DataColumns.IS_SWAP, true);
Uri uri = RepoProvider.Helper.insert(this, values);
repo = RepoProvider.Helper.findByUri(this, uri);
} else if (!repo.isSwap) {
Log.d(TAG, "Old local repo being marked as \"Swap\" repo, so that it wont appear in the list of repositories in the future.");
ContentValues values = new ContentValues(1);
values.put(RepoProvider.DataColumns.IS_SWAP, true);
RepoProvider.Helper.update(this, repo, values);
}
if (!newRepoConfig.preventFurtherSwaps()) {

查看文件

@ -34,54 +34,54 @@ public class UtilsTest extends AndroidTestCase {
String fingerprintLongByOnePubkey = "308203c5308202ada00302010202047b7cf549300d06092a864886f70d01010b0500308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f301e170d3132313032393130323530305a170d3430303331363130323530305a308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f30820122300d06092a864886f70d01010105000382010f003082010a0282010100b7f1f635fa3fce1a8042aaa960c2dc557e4ad2c082e5787488cba587fd26207cf59507919fc4dcebda5c8c0959d14146d0445593aa6c29dc639570b71712451fd5c231b0c9f5f0bec380503a1c2a3bc00048bc5db682915afa54d1ecf67b45e1e05c0934b3037a33d3a565899131f27a72c03a5de93df17a2376cc3107f03ee9d124c474dfab30d4053e8f39f292e2dcb6cc131bce12a0c5fc307985195d256bf1d7a2703d67c14bf18ed6b772bb847370b20335810e337c064fef7e2795a524c664a853cd46accb8494f865164dabfb698fa8318236432758bc40d52db00d5ce07fe2210dc06cd95298b4f09e6c9b7b7af61c1d62ea43ea36a2331e7b2d4e250203010001a321301f301d0603551d0e0416041404d763e981cf3a295b94a790d8536a783097232b300d06092a864886f70d01010b05000382010100654e6484ff032c54fed1d96d3c8e731302be9dbd7bb4fe635f2dac05b69f3ecbb5acb7c9fe405e2a066567a8f5c2beb8b199b5a4d5bb1b435cf02df026d4fb4edd9d8849078f085b00950083052d57467d65c6eebd98f037cff9b148d621cf8819c4f7dc1459bf8fc5c7d76f901495a7caf35d1e5c106e1d50610c4920c3c1b50adcfbd4ad83ce7353cdea7d856bba0419c224f89a2f3ebc203d20eb6247711ad2b55fd4737936dc42ced7a047cbbd24012079204a2883b6d55d5d5b66d9fd82fb51fca9a5db5fad9af8564cb380ff30ae8263dbbf01b46e01313f53279673daa3f893380285646b244359203e7eecde94ae141b7dfa8e6499bb8e7e0b25ab85";
public void testFormatFingerprint() {
String badResult = Utils.formatFingerprint("");
String badResult = Utils.formatFingerprint(getContext(), "");
// real fingerprints
String formatted = null;
formatted = Utils.formatFingerprint(fdroidFingerprint);
String formatted;
formatted = Utils.formatFingerprint(getContext(), fdroidFingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
formatted = Utils.formatFingerprint(gpRepoFingerprint);
formatted = Utils.formatFingerprint(getContext(), gpRepoFingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
formatted = Utils.formatFingerprint(gpTest1Fingerprint);
formatted = Utils.formatFingerprint(getContext(), gpTest1Fingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
// random garbage
assertEquals(
badResult,
Utils.formatFingerprint("234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja"));
Utils.formatFingerprint(getContext(), "234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja"));
assertEquals(
badResult,
Utils.formatFingerprint("g000000000000000000000000000000000000000000000000000000000000000"));
Utils.formatFingerprint(getContext(), "g000000000000000000000000000000000000000000000000000000000000000"));
assertEquals(
badResult,
Utils.formatFingerprint("98273498723948728934789237489273p1928731982731982739182739817238"));
Utils.formatFingerprint(getContext(), "98273498723948728934789237489273p1928731982731982739182739817238"));
// too short
assertEquals(
badResult,
Utils.formatFingerprint("C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5"));
Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5"));
assertEquals(
badResult,
Utils.formatFingerprint("C63AED1"));
Utils.formatFingerprint(getContext(), "C63AED1"));
assertEquals(
badResult,
Utils.formatFingerprint("f"));
Utils.formatFingerprint(getContext(), "f"));
assertEquals(
badResult,
Utils.formatFingerprint(""));
Utils.formatFingerprint(getContext(), ""));
assertEquals(
badResult,
Utils.formatFingerprint(null));
Utils.formatFingerprint(getContext(), null));
// real digits but too long
assertEquals(
badResult,
Utils.formatFingerprint("43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB"));
Utils.formatFingerprint(getContext(), "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB"));
assertEquals(
badResult,
Utils.formatFingerprint("C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F"));
Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F"));
assertEquals(
badResult,
Utils.formatFingerprint("3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"));
Utils.formatFingerprint(getContext(), "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"));
}
public void testCalcFingerprintString() {