Tolerate multiple signatures on index

This commit is contained in:
Henrik Tunedal 2011-03-18 18:03:02 +01:00
parent 6950085b56
commit fabea142da

View File

@ -30,6 +30,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.cert.Certificate;
import java.util.Vector; import java.util.Vector;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
@ -266,53 +267,65 @@ public class RepoXMLHandler extends DefaultHandler {
Log.d("FDroid", "Getting signed index from " Log.d("FDroid", "Getting signed index from "
+ repo.address); + repo.address);
getRemoteFile(ctx, repo.address + "/index.jar", getRemoteFile(ctx, repo.address + "/index.jar",
"tempindex.jar"); "tempindex.jar");
String jarpath = ctx.getFilesDir() + "/tempindex.jar"; String jarpath = ctx.getFilesDir()
JarFile jar = new JarFile(jarpath); + "/tempindex.jar";
JarEntry je = (JarEntry) jar.getEntry("index.xml"); JarFile jar;
File efile = new File(ctx.getFilesDir(), JarEntry je;
"/tempindex.xml"); try {
InputStream in = new BufferedInputStream(jar jar = new JarFile(jarpath, true);
.getInputStream(je), 8192); je = (JarEntry) jar.getEntry("index.xml");
OutputStream out = new BufferedOutputStream( File efile = new File(ctx.getFilesDir(),
new FileOutputStream(efile), 8192); "/tempindex.xml");
byte[] buffer = new byte[8192]; InputStream in = new BufferedInputStream(jar
while (true) { .getInputStream(je), 8192);
int nBytes = in.read(buffer); OutputStream out = new BufferedOutputStream(
if (nBytes <= 0) new FileOutputStream(efile), 8192);
break; byte[] buffer = new byte[8192];
out.write(buffer, 0, nBytes); while (true) {
int nBytes = in.read(buffer);
if (nBytes <= 0)
break;
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
} catch (SecurityException e) {
Log.e("FDroid", "Invalid hash for index file");
return false;
} }
out.flush(); Certificate[] certs = je.getCertificates();
out.close();
in.close();
java.security.cert.Certificate[] certs = je
.getCertificates();
jar.close(); jar.close();
if (certs == null) { if (certs == null) {
Log.d("FDroid", "No signature found in index"); Log.d("FDroid", "No signature found in index");
return false; return false;
} }
if (certs.length != 1) { Log.d("FDroid", "Index has "
Log.d("FDroid", "Expected one signature - found " + certs.length + " signature"
+ certs.length); + (certs.length > 1 ? "s." : "."));
return false;
}
byte[] sig = certs[0].getEncoded(); boolean match = false;
byte[] csig = new byte[sig.length * 2]; for (Certificate cert : certs) {
for (int j = 0; j < sig.length; j++) { byte[] sig = cert.getEncoded();
byte v = sig[j]; byte[] csig = new byte[sig.length * 2];
int d = (v >> 4) & 0xf; for (int j = 0; j < sig.length; j++) {
csig[j * 2] = (byte) (d >= 10 ? ('a' + d - 10) byte v = sig[j];
: ('0' + d)); int d = (v >> 4) & 0xf;
d = v & 0xf; csig[j * 2] = (byte) (d >= 10
csig[j * 2 + 1] = (byte) (d >= 10 ? ('a' + d - 10) ? ('a' + d - 10)
: ('0' + d)); : ('0' + d));
d = v & 0xf;
csig[j * 2 + 1] = (byte) (d >= 10
? ('a' + d - 10)
: ('0' + d));
}
if (repo.pubkey.equals(new String(csig))) {
match = true;
break;
}
} }
String ssig = new String(csig); if (!match) {
if (!ssig.equals(repo.pubkey)) {
Log.d("FDroid", "Index signature mismatch"); Log.d("FDroid", "Index signature mismatch");
return false; return false;
} }