fix swap to follow repo.fingerprint logic: null means unset

The repo.fingerprint logic is based on null meaning that the fingerprint
has not been set.  This ensures that a "" does not sneak in somehow as a
valid fingerprint.
This commit is contained in:
Hans-Christoph Steiner 2015-09-11 14:09:56 +02:00
parent 03d074a0e8
commit 69b210a4b8
6 changed files with 52 additions and 13 deletions

View File

@ -2,6 +2,7 @@ package javax.jmdns.impl;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import java.net.Inet4Address;
import java.net.Inet6Address;
@ -21,8 +22,21 @@ public class FDroidServiceInfo extends ServiceInfoImpl implements Parcelable {
super(info);
}
/**
* Return the fingerprint of the signing key, or {@code null} if it is not set.
*/
public String getFingerprint() {
return getPropertyString("fingerprint");
// getPropertyString() will return "true" if the value is a zero-length byte array
// so we just do a custom version using getPropertyBytes()
byte[] data = getPropertyBytes("fingerprint");
if (data == null || data.length == 0) {
return null;
}
String fingerprint = this.readUTF(data, 0, data.length);
if (TextUtils.isEmpty(fingerprint)) {
return null;
}
return fingerprint;
}
public String getRepoAddress() {

View File

@ -36,6 +36,14 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* Handles getting the index metadata for an app repo, then verifying the
* signature on the index metdata, implementing as a JAR signature.
* <p/>
* <b>WARNING</b>: this class is the central piece of the entire security model of
* FDroid! Avoid modifying it when possible, if you absolutely must, be very,
* very careful with the changes that you are making!
*/
public class RepoUpdater {
private static final String TAG = "RepoUpdater";
@ -280,7 +288,8 @@ public class RepoUpdater {
* actually in the index.jar itself. If no fingerprint, just store the
* signing certificate */
boolean trustNewSigningCertificate = false;
if (TextUtils.isEmpty(repo.fingerprint)) {
// If the fingerprint has never been set, it will be null (never "" or something else)
if (repo.fingerprint == null) {
// no info to check things are valid, so just Trust On First Use
trustNewSigningCertificate = true;
} else {
@ -290,7 +299,8 @@ public class RepoUpdater {
&& repo.fingerprint.equalsIgnoreCase(fingerprintFromJar)) {
trustNewSigningCertificate = true;
} else {
throw new UpdateException(repo, "Supplied certificate fingerprint does not match!");
throw new UpdateException(repo, "Supplied certificate fingerprint does not match: '"
+ repo.fingerprint + "' '" + fingerprintFromIndexXml + "' '" + fingerprintFromJar + "'");
}
}

View File

@ -19,13 +19,21 @@ public class Repo extends ValueObject {
public String address;
public String name;
public String description;
public int version; // index version, i.e. what fdroidserver built it - 0 if not specified
/** index version, i.e. what fdroidserver built it - 0 if not specified */
public int version;
public boolean inuse;
public int priority;
public String pubkey; // null for an unsigned repo
public String fingerprint; // always null for an unsigned repo
public int maxage; // maximum age of index that will be accepted - 0 for any
public String lastetag; // last etag we updated from, null forces update
/** The signing certificate, {@code null} for a newly added repo */
public String pubkey;
/**
* The SHA1 fingerprint of {@link #pubkey}, set to {@code null} when a
* newly added repo did not include fingerprint. It should never be an
* empty {@link String}, i.e. {@code ""} */
public String fingerprint;
/** maximum age of index that will be accepted - 0 for any */
public int maxage;
/** last etag we updated from, null forces update */
public String lastetag;
public Date lastUpdated;
public boolean isSwap;

View File

@ -259,7 +259,9 @@ public class SwapService extends Service {
values.put(RepoProvider.DataColumns.NAME, peer.getName());
values.put(RepoProvider.DataColumns.ADDRESS, peer.getRepoAddress());
values.put(RepoProvider.DataColumns.DESCRIPTION, "");
values.put(RepoProvider.DataColumns.FINGERPRINT, peer.getFingerprint());
String fingerprint = peer.getFingerprint();
if (!TextUtils.isEmpty(fingerprint))
values.put(RepoProvider.DataColumns.FINGERPRINT, peer.getFingerprint());
values.put(RepoProvider.DataColumns.IN_USE, true);
values.put(RepoProvider.DataColumns.IS_SWAP, true);
Uri uri = RepoProvider.Helper.insert(this, values);

View File

@ -40,13 +40,15 @@ public class BluetoothPeer implements Peer {
}
/**
* Bluetooth will exclusively be TOFU. Once a device is connected to a bluetooth socket,
* if we trust it enough to accept a fingerprint from it somehow, then we may as well trust it
* enough to receive an index from it that contains a fingerprint we can use.
* Return the fingerprint of the signing key, or {@code null} if it is not set.
* <p/>
* This is not yet stored for Bluetooth connections. Once a device is connected to a bluetooth
* socket, if we trust it enough to accept a fingerprint from it somehow, then we may as well
* trust it enough to receive an index from it that contains a fingerprint we can use.
*/
@Override
public String getFingerprint() {
return "";
return null;
}
@Override

View File

@ -41,6 +41,9 @@ public class BonjourPeer extends WifiPeer {
return serviceInfo.getRepoAddress();
}
/**
* Return the fingerprint of the signing key, or {@code null} if it is not set.
*/
@Override
public String getFingerprint() {
return serviceInfo.getFingerprint();