add detailed checking of incoming repos based on fingerprint in DB

When a new repo is being added, whether manually or via an incoming Intent,
check the address and fingerprint against repos in the DB.  If the repo is
not in the DB, offer to add it.  If the repo address is in the DB, then do
more checks:

* If that address has no fingerprint in the DB, then offer to add the new
  repo including that fingerprint.  This might happen when upgrading a repo
  from unsigned to signed.
* if the incoming info matches a repo in the DB, offer to enable that repo
* if the address matches a repo in the DB but the incoming fingerprint does
  not match the fingerprint in the DB, warn the user, and tell them to
  delete the existing repo if they truly want to override the existing info
This commit is contained in:
Hans-Christoph Steiner 2013-12-02 20:12:52 -05:00
parent 711a1418b6
commit c7b076e5ea
3 changed files with 86 additions and 51 deletions

View File

@ -4,17 +4,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" > android:orientation="vertical" >
<TextView
android:id="@+id/repo_alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_dialog_alert"
android:gravity="center"
android:text="@string/repo_exists"
android:textAppearance="@android:style/TextAppearance.Large"
android:textColor="@color/red"
android:visibility="gone" />
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -25,7 +14,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textUri" android:inputType="textUri"
android:maxLines="1" android:maxLines="2"
android:text="https://" /> android:text="https://" />
<TextView <TextView
@ -39,15 +28,17 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:digits="0123456789ABCDEFabcedf: " android:digits="0123456789ABCDEFabcedf: "
android:inputType="textNoSuggestions" android:inputType="textNoSuggestions"
android:maxLines="1" android:maxLines="3"
android:typeface="monospace" /> android:typeface="monospace" />
<CheckBox <TextView
android:id="@+id/overwrite_repo" android:id="@+id/overwrite_message"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableLeft="@android:drawable/ic_dialog_alert"
android:drawablePadding="20dp"
android:padding="20dp" android:padding="20dp"
android:text="@string/repo_overwrite" android:text="@string/repo_delete_to_overwrite"
android:textAppearance="@android:style/TextAppearance.Medium" android:textAppearance="@android:style/TextAppearance.Medium"
android:visibility="gone" /> android:visibility="gone" />

View File

@ -56,6 +56,9 @@
<string name="repo_add_add">Add</string> <string name="repo_add_add">Add</string>
<string name="cancel">Cancel</string> <string name="cancel">Cancel</string>
<string name="enable">Enable</string>
<string name="add_key">Add Key</string>
<string name="overwrite">Overwrite</string>
<string name="repo_delete_title">Choose repository to remove</string> <string name="repo_delete_title">Choose repository to remove</string>
<string name="repo_update_title">Update repositories</string> <string name="repo_update_title">Update repositories</string>
@ -72,7 +75,9 @@
<string name="repo_add_url">Repository address</string> <string name="repo_add_url">Repository address</string>
<string name="repo_add_fingerprint">fingerprint (optional)</string> <string name="repo_add_fingerprint">fingerprint (optional)</string>
<string name="repo_exists">This repo already exists!</string> <string name="repo_exists">This repo already exists!</string>
<string name="repo_overwrite">Overwrite the existing repo?</string> <string name="repo_exists_add_fingerprint">This repo is already setup, this will add new key information.</string>
<string name="repo_exists_enable">This repo is already setup, confirm that you want to re-enable it.</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="repo_alrt">The list of used repositories has <string name="repo_alrt">The list of used repositories has
changed.\nDo you changed.\nDo you

View File

@ -35,24 +35,21 @@ import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v4.view.MenuItemCompat;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SimpleAdapter; import android.widget.SimpleAdapter;
import android.widget.TextView; import android.widget.TextView;
import org.fdroid.fdroid.DB.Repo; import org.fdroid.fdroid.DB.Repo;
import android.support.v4.app.NavUtils;
import android.support.v4.view.MenuItemCompat;
import org.fdroid.fdroid.compat.ActionBarCompat; import org.fdroid.fdroid.compat.ActionBarCompat;
public class ManageRepo extends ListActivity { public class ManageRepo extends ListActivity {
@ -62,6 +59,11 @@ public class ManageRepo extends ListActivity {
private boolean changed = false; private boolean changed = false;
private enum PositiveAction {
ADD_NEW, ENABLE, IGNORE
}
private PositiveAction positiveAction;
private List<DB.Repo> repos; private List<DB.Repo> repos;
private static List<String> reposToDisable; private static List<String> reposToDisable;
@ -231,10 +233,10 @@ public class ManageRepo extends ListActivity {
return repos; return repos;
} }
protected Repo getRepo(String repoUri, List<Repo> repos) { protected Repo getRepoByAddress(String address, List<Repo> repos) {
if (repoUri != null) if (address != null)
for (Repo repo : repos) for (Repo repo : repos)
if (repoUri.equals(repo.address)) if (address.equals(repo.address))
return repo; return repo;
return null; return null;
} }
@ -249,7 +251,7 @@ public class ManageRepo extends ListActivity {
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void showAddRepo(String uriString, String fingerprint) { private void showAddRepo(String newAddress, String newFingerprint) {
LayoutInflater li = LayoutInflater.from(this); LayoutInflater li = LayoutInflater.from(this);
View view = li.inflate(R.layout.addrepo, null); View view = li.inflate(R.layout.addrepo, null);
Builder p = new AlertDialog.Builder(this).setView(view); Builder p = new AlertDialog.Builder(this).setView(view);
@ -257,6 +259,9 @@ public class ManageRepo extends ListActivity {
final EditText uriEditText = (EditText) view.findViewById(R.id.edit_uri); final EditText uriEditText = (EditText) view.findViewById(R.id.edit_uri);
final EditText fingerprintEditText = (EditText) view.findViewById(R.id.edit_fingerprint); final EditText fingerprintEditText = (EditText) view.findViewById(R.id.edit_fingerprint);
List<Repo> repos = getRepos();
final Repo repo = getRepoByAddress(newAddress, repos);
alrt.setIcon(android.R.drawable.ic_menu_add); alrt.setIcon(android.R.drawable.ic_menu_add);
alrt.setTitle(getString(R.string.repo_add_title)); alrt.setTitle(getString(R.string.repo_add_title));
alrt.setButton(DialogInterface.BUTTON_POSITIVE, alrt.setButton(DialogInterface.BUTTON_POSITIVE,
@ -264,10 +269,15 @@ public class ManageRepo extends ListActivity {
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
addRepo(uriEditText.getText().toString(), String fp = fingerprintEditText.getText().toString();
fingerprintEditText.getText().toString()); // the DB uses null for no fingerprint but the above
changed = true; // code returns "" rather than null if its blank
redraw(); if (fp.equals(""))
fp = null;
if (positiveAction == PositiveAction.ADD_NEW)
addRepoPositiveAction(uriEditText.getText().toString(), fp, null);
else if (positiveAction == PositiveAction.ENABLE)
addRepoPositiveAction(null, null, repo);
} }
}); });
@ -281,30 +291,59 @@ public class ManageRepo extends ListActivity {
}); });
alrt.show(); alrt.show();
List<Repo> repos = getRepos(); final TextView overwriteMessage = (TextView) view.findViewById(R.id.overwrite_message);
Repo repo = getRepo(uriString, repos); overwriteMessage.setVisibility(View.GONE);
if (repo != null) { if (repo == null) {
TextView tv = (TextView) view.findViewById(R.id.repo_alert); // no existing repo, add based on what we have
tv.setVisibility(0); positiveAction = PositiveAction.ADD_NEW;
tv.setText(R.string.repo_exists); } else {
// found the address in the DB of existing repos
final Button addButton = alrt.getButton(DialogInterface.BUTTON_POSITIVE); final Button addButton = alrt.getButton(DialogInterface.BUTTON_POSITIVE);
addButton.setEnabled(false); alrt.setTitle(R.string.repo_exists);
final CheckBox overwriteCheckBox = (CheckBox) view.findViewById(R.id.overwrite_repo); overwriteMessage.setVisibility(View.VISIBLE);
overwriteCheckBox.setVisibility(0); if (repo.fingerprint == null && newFingerprint != null) {
overwriteCheckBox.setOnClickListener(new OnClickListener() { // we're upgrading from unsigned to signed repo
@Override overwriteMessage.setText(R.string.repo_exists_add_fingerprint);
public void onClick(View v) { addButton.setText(R.string.add_key);
addButton.setEnabled(overwriteCheckBox.isChecked()); positiveAction = PositiveAction.ADD_NEW;
} } else if (newFingerprint == null || newFingerprint.equals(repo.fingerprint)) {
}); // this entry already exists, offer to enable it
// TODO if address and fingerprint match, then enable existing repo overwriteMessage.setText(R.string.repo_exists_enable);
// TODO if address matches but fingerprint doesn't, handle this with extra widgets addButton.setText(R.string.enable);
positiveAction = PositiveAction.ENABLE;
} else {
// same address with different fingerprint, this could be
// malicious, so force the user to manually delete the repo
// before adding this one
overwriteMessage.setTextColor(getResources().getColor(R.color.red));
overwriteMessage.setText(R.string.repo_delete_to_overwrite);
addButton.setText(R.string.overwrite);
addButton.setEnabled(false);
positiveAction = PositiveAction.IGNORE;
}
} }
if (uriString != null) if (newAddress != null)
uriEditText.setText(uriString); uriEditText.setText(newAddress);
if (fingerprint != null) if (newFingerprint != null)
fingerprintEditText.setText(fingerprint); fingerprintEditText.setText(newFingerprint);
}
private void addRepoPositiveAction(String address, String fingerprint, Repo repo) {
if (address != null) {
addRepo(address, fingerprint);
} else if (repo != null) {
// force-enable an existing repo
repo.inuse = true;
try {
DB db = DB.getDB();
db.updateRepoByAddress(repo);
} finally {
DB.releaseDB();
}
}
changed = true;
redraw();
} }
@Override @Override