Merge branch 'fix-111/lollipop-sadness' into 'master'
Fix issue #111 (Doesn't work on lollipop devices) See Issue #111 (monster comment https://gitlab.com/fdroid/fdroidclient/issues/111#note_379713) for details of fix. See merge request !41
This commit is contained in:
commit
f0dba2f6e7
@ -55,10 +55,8 @@ import org.fdroid.fdroid.localrepo.LocalRepoService;
|
|||||||
import org.fdroid.fdroid.net.IconDownloader;
|
import org.fdroid.fdroid.net.IconDownloader;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.Security;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class FDroidApp extends Application {
|
public class FDroidApp extends Application {
|
||||||
@ -71,6 +69,8 @@ public class FDroidApp extends Application {
|
|||||||
public static Repo repo = new Repo();
|
public static Repo repo = new Repo();
|
||||||
public static Set<String> selectedApps = null; // init in SelectLocalAppsFragment
|
public static Set<String> selectedApps = null; // init in SelectLocalAppsFragment
|
||||||
|
|
||||||
|
// Leaving the fully qualified class name here to help clarify the difference between spongy/bouncy castle.
|
||||||
|
private static org.spongycastle.jce.provider.BouncyCastleProvider spongyCastleProvider;
|
||||||
private static Messenger localRepoServiceMessenger = null;
|
private static Messenger localRepoServiceMessenger = null;
|
||||||
private static boolean localRepoServiceIsBound = false;
|
private static boolean localRepoServiceIsBound = false;
|
||||||
|
|
||||||
@ -78,6 +78,11 @@ public class FDroidApp extends Application {
|
|||||||
|
|
||||||
BluetoothAdapter bluetoothAdapter = null;
|
BluetoothAdapter bluetoothAdapter = null;
|
||||||
|
|
||||||
|
static {
|
||||||
|
spongyCastleProvider = new org.spongycastle.jce.provider.BouncyCastleProvider();
|
||||||
|
enableSpongyCastle();
|
||||||
|
}
|
||||||
|
|
||||||
public static enum Theme {
|
public static enum Theme {
|
||||||
dark, light, lightWithDarkActionBar
|
dark, light, lightWithDarkActionBar
|
||||||
}
|
}
|
||||||
@ -108,6 +113,22 @@ public class FDroidApp extends Application {
|
|||||||
return curTheme;
|
return curTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void enableSpongyCastle() {
|
||||||
|
Security.addProvider(spongyCastleProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableSpongyCastleOnLollipop() {
|
||||||
|
if (Build.VERSION.SDK_INT == 21) {
|
||||||
|
Security.addProvider(spongyCastleProvider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableSpongyCastleOnLollipop() {
|
||||||
|
if (Build.VERSION.SDK_INT == 21) {
|
||||||
|
Security.removeProvider(spongyCastleProvider.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
@ -11,6 +11,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.AppFilter;
|
import org.fdroid.fdroid.AppFilter;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -263,6 +264,11 @@ public class App extends ValueObject implements Comparable<App> {
|
|||||||
throw new CertificateEncodingException("null signed entry!");
|
throw new CertificateEncodingException("null signed entry!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Due to a bug in android 5.0 lollipop, the inclusion of BouncyCastle causes
|
||||||
|
// breakage when verifying the signature of most .jars. For more
|
||||||
|
// details, check out https://gitlab.com/fdroid/fdroidclient/issues/111.
|
||||||
|
try {
|
||||||
|
FDroidApp.disableSpongyCastleOnLollipop();
|
||||||
InputStream tmpIn = apkJar.getInputStream(aSignedEntry);
|
InputStream tmpIn = apkJar.getInputStream(aSignedEntry);
|
||||||
byte[] buff = new byte[2048];
|
byte[] buff = new byte[2048];
|
||||||
while (tmpIn.read(buff, 0, buff.length) != -1) {
|
while (tmpIn.read(buff, 0, buff.length) != -1) {
|
||||||
@ -281,7 +287,9 @@ public class App extends ValueObject implements Comparable<App> {
|
|||||||
|
|
||||||
Certificate signer = aSignedEntry.getCertificates()[0];
|
Certificate signer = aSignedEntry.getCertificates()[0];
|
||||||
rawCertBytes = signer.getEncoded();
|
rawCertBytes = signer.getEncoded();
|
||||||
|
} finally {
|
||||||
|
FDroidApp.enableSpongyCastleOnLollipop();
|
||||||
|
}
|
||||||
apkJar.close();
|
apkJar.close();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -34,12 +34,8 @@ import kellinwood.security.zipsigner.ZipSigner;
|
|||||||
// TODO Address exception handling in a uniform way throughout
|
// TODO Address exception handling in a uniform way throughout
|
||||||
|
|
||||||
public class LocalRepoKeyStore {
|
public class LocalRepoKeyStore {
|
||||||
private static final String TAG = "KerplappKeyStore";
|
|
||||||
|
|
||||||
static {
|
private static final String TAG = "org.fdroid.fdroid.localrepo.LocalRepoKeyStore";
|
||||||
Security.insertProviderAt(
|
|
||||||
new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String INDEX_CERT_ALIAS = "fdroid";
|
public static final String INDEX_CERT_ALIAS = "fdroid";
|
||||||
public static final String HTTP_CERT_ALIAS = "https";
|
public static final String HTTP_CERT_ALIAS = "https";
|
||||||
@ -55,26 +51,49 @@ public class LocalRepoKeyStore {
|
|||||||
private KeyManager[] keyManagers;
|
private KeyManager[] keyManagers;
|
||||||
private File keyStoreFile;
|
private File keyStoreFile;
|
||||||
|
|
||||||
public static LocalRepoKeyStore get(Context context) {
|
public static LocalRepoKeyStore get(Context context) throws InitException {
|
||||||
if (localRepoKeyStore == null)
|
if (localRepoKeyStore == null)
|
||||||
localRepoKeyStore = new LocalRepoKeyStore(context);
|
localRepoKeyStore = new LocalRepoKeyStore(context);
|
||||||
return localRepoKeyStore;
|
return localRepoKeyStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalRepoKeyStore(Context context) {
|
public static class InitException extends Exception {
|
||||||
|
public InitException(String detailMessage) {
|
||||||
|
super(detailMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalRepoKeyStore(Context context) throws InitException {
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "generating LocalRepoKeyStore instance");
|
|
||||||
File appKeyStoreDir = context.getDir("keystore", Context.MODE_PRIVATE);
|
File appKeyStoreDir = context.getDir("keystore", Context.MODE_PRIVATE);
|
||||||
|
|
||||||
|
Log.d(TAG, "Generating LocalRepoKeyStore instance: " + appKeyStoreDir.getAbsolutePath());
|
||||||
this.keyStoreFile = new File(appKeyStoreDir, "kerplapp.bks");
|
this.keyStoreFile = new File(appKeyStoreDir, "kerplapp.bks");
|
||||||
|
|
||||||
|
Log.d(TAG, "Using default KeyStore type: " + KeyStore.getDefaultType());
|
||||||
this.keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
this.keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
|
|
||||||
|
if (keyStoreFile.exists()) {
|
||||||
|
try {
|
||||||
|
Log.d(TAG, "Keystore already exists, loading...");
|
||||||
|
keyStore.load(new FileInputStream(keyStoreFile), "".toCharArray());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Error while loading existing keystore. Will delete and create a new one.");
|
||||||
|
|
||||||
|
// NOTE: Could opt to delete and then re-create the keystore here, but that may
|
||||||
|
// be undesirable. For example - if you were to re-connect to an existing device
|
||||||
|
// that you have swapped apps with in the past, then you would really want the
|
||||||
|
// signature to be the same as last time.
|
||||||
|
throw new InitException("Could not initialize local repo keystore: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyStoreFile.exists()) {
|
||||||
// If there isn't a persisted BKS keystore on disk we need to
|
// If there isn't a persisted BKS keystore on disk we need to
|
||||||
// create a new empty keystore
|
// create a new empty keystore
|
||||||
if (!keyStoreFile.exists()) {
|
|
||||||
// Init a new keystore with a blank passphrase
|
// Init a new keystore with a blank passphrase
|
||||||
|
Log.d(TAG, "Keystore doesn't exist, creating...");
|
||||||
keyStore.load(null, "".toCharArray());
|
keyStore.load(null, "".toCharArray());
|
||||||
} else {
|
|
||||||
keyStore.load(new FileInputStream(keyStoreFile), "".toCharArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -119,17 +138,23 @@ public class LocalRepoKeyStore {
|
|||||||
wrappedKeyManager
|
wrappedKeyManager
|
||||||
};
|
};
|
||||||
} catch (UnrecoverableKeyException e) {
|
} catch (UnrecoverableKeyException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (OperatorCreationException e) {
|
} catch (OperatorCreationException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error loading keystore: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +175,8 @@ public class LocalRepoKeyStore {
|
|||||||
FDroidApp.ipAddressString);
|
FDroidApp.ipAddressString);
|
||||||
addToStore(HTTP_CERT_ALIAS, kerplappKeypair, indexCert);
|
addToStore(HTTP_CERT_ALIAS, kerplappKeypair, indexCert);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Failed to setup HTTPS certificate: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,21 +206,29 @@ public class LocalRepoKeyStore {
|
|||||||
zipSigner.signZip(input.getAbsolutePath(), output.getAbsolutePath());
|
zipSigner.signZip(input.getAbsolutePath(), output.getAbsolutePath());
|
||||||
|
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (InstantiationException e) {
|
} catch (InstantiationException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (UnrecoverableKeyException e) {
|
} catch (UnrecoverableKeyException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to sign local repo index: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,11 +257,14 @@ public class LocalRepoKeyStore {
|
|||||||
if (key instanceof PrivateKey)
|
if (key instanceof PrivateKey)
|
||||||
return keyStore.getCertificate(INDEX_CERT_ALIAS);
|
return keyStore.getCertificate(INDEX_CERT_ALIAS);
|
||||||
} catch (KeyStoreException e) {
|
} catch (KeyStoreException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to get certificate for local repo: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (UnrecoverableKeyException e) {
|
} catch (UnrecoverableKeyException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to get certificate for local repo: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Unable to get certificate for local repo: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,8 @@ public class LocalRepoManager {
|
|||||||
symlinkIndexPageElsewhere("../../", repoCAPS);
|
symlinkIndexPageElsewhere("../../", repoCAPS);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error writing local repo index: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,13 +250,16 @@ public class LocalRepoManager {
|
|||||||
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_META_DATA);
|
||||||
app.icon = getIconFile(packageName, packageInfo.versionCode).getName();
|
app.icon = getIconFile(packageName, packageInfo.versionCode).getName();
|
||||||
} catch (NameNotFoundException e) {
|
} catch (NameNotFoundException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error adding app to local repo: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
return;
|
return;
|
||||||
} catch (CertificateEncodingException e) {
|
} catch (CertificateEncodingException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error adding app to local repo: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error adding app to local repo: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "apps.put: " + packageName);
|
Log.i(TAG, "apps.put: " + packageName);
|
||||||
@ -317,7 +321,7 @@ public class LocalRepoManager {
|
|||||||
|
|
||||||
// TODO this needs to be ported to < android-8
|
// TODO this needs to be ported to < android-8
|
||||||
@TargetApi(8)
|
@TargetApi(8)
|
||||||
private void writeIndexXML() throws TransformerException, ParserConfigurationException {
|
private void writeIndexXML() throws TransformerException, ParserConfigurationException, LocalRepoKeyStore.InitException {
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
|
||||||
@ -480,12 +484,11 @@ public class LocalRepoManager {
|
|||||||
writeIndexXML();
|
writeIndexXML();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toast.makeText(context, R.string.failed_to_create_index, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.failed_to_create_index, Toast.LENGTH_LONG).show();
|
||||||
e.printStackTrace();
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedOutputStream bo = new BufferedOutputStream(
|
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(xmlIndexJarUnsigned));
|
||||||
new FileOutputStream(xmlIndexJarUnsigned));
|
|
||||||
JarOutputStream jo = new JarOutputStream(bo);
|
JarOutputStream jo = new JarOutputStream(bo);
|
||||||
|
|
||||||
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(xmlIndex));
|
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(xmlIndex));
|
||||||
@ -504,8 +507,13 @@ public class LocalRepoManager {
|
|||||||
jo.close();
|
jo.close();
|
||||||
bo.close();
|
bo.close();
|
||||||
|
|
||||||
|
try {
|
||||||
LocalRepoKeyStore.get(context).signZip(xmlIndexJarUnsigned, xmlIndexJar);
|
LocalRepoKeyStore.get(context).signZip(xmlIndexJarUnsigned, xmlIndexJar);
|
||||||
|
} catch (LocalRepoKeyStore.InitException e) {
|
||||||
|
throw new IOException("Could not sign index - keystore failed to initialize");
|
||||||
|
} finally {
|
||||||
xmlIndexJarUnsigned.delete();
|
xmlIndexJarUnsigned.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import org.fdroid.fdroid.FDroidApp;
|
|||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.Preferences.ChangeListener;
|
import org.fdroid.fdroid.Preferences.ChangeListener;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.Utils;
|
||||||
import org.fdroid.fdroid.net.LocalHTTPD;
|
import org.fdroid.fdroid.net.LocalHTTPD;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
import org.fdroid.fdroid.views.swap.SwapActivity;
|
import org.fdroid.fdroid.views.swap.SwapActivity;
|
||||||
@ -226,7 +227,8 @@ public class LocalRepoService extends Service {
|
|||||||
Log.w(TAG, "port " + prev + " occupied, trying on " + FDroidApp.port + "!");
|
Log.w(TAG, "port " + prev + " occupied, trying on " + FDroidApp.port + "!");
|
||||||
startService(new Intent(LocalRepoService.this, WifiStateChangeService.class));
|
startService(new Intent(LocalRepoService.this, WifiStateChangeService.class));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Could not start local repo HTTP server: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
Looper.loop(); // start the message receiving loop
|
Looper.loop(); // start the message receiving loop
|
||||||
}
|
}
|
||||||
@ -279,7 +281,8 @@ public class LocalRepoService extends Service {
|
|||||||
jmdns = JmDNS.create();
|
jmdns = JmDNS.create();
|
||||||
jmdns.registerService(pairService);
|
jmdns.registerService(pairService);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Error while registering jmdns service: " + e);
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
@ -300,11 +303,7 @@ public class LocalRepoService extends Service {
|
|||||||
pairService = null;
|
pairService = null;
|
||||||
}
|
}
|
||||||
jmdns.unregisterAllServices();
|
jmdns.unregisterAllServices();
|
||||||
try {
|
Utils.closeQuietly(jmdns);
|
||||||
jmdns.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
jmdns = null;
|
jmdns = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,11 @@ public class LocalHTTPD extends NanoHTTPD {
|
|||||||
localRepoKeyStore.getKeyManagers());
|
localRepoKeyStore.getKeyManagers());
|
||||||
makeSecure(factory);
|
makeSecure(factory);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, "Could not enable HTTPS: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
} catch (LocalRepoKeyStore.InitException e) {
|
||||||
|
Log.e(TAG, "Could not enable HTTPS: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,9 +82,6 @@ public class WifiStateChangeService extends Service {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
Context context = WifiStateChangeService.this.getApplicationContext();
|
Context context = WifiStateChangeService.this.getApplicationContext();
|
||||||
LocalRepoKeyStore localRepoKeyStore = LocalRepoKeyStore.get(context);
|
|
||||||
Certificate localCert = localRepoKeyStore.getCertificate();
|
|
||||||
FDroidApp.repo.fingerprint = Utils.calcFingerprint(localCert);
|
|
||||||
LocalRepoManager lrm = LocalRepoManager.get(context);
|
LocalRepoManager lrm = LocalRepoManager.get(context);
|
||||||
lrm.setUriString(FDroidApp.repo.address);
|
lrm.setUriString(FDroidApp.repo.address);
|
||||||
lrm.writeIndexPage(Utils.getSharingUri(context, FDroidApp.repo).toString());
|
lrm.writeIndexPage(Utils.getSharingUri(context, FDroidApp.repo).toString());
|
||||||
@ -92,6 +89,11 @@ public class WifiStateChangeService extends Service {
|
|||||||
if (isCancelled())
|
if (isCancelled())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
LocalRepoKeyStore localRepoKeyStore = LocalRepoKeyStore.get(context);
|
||||||
|
Certificate localCert = localRepoKeyStore.getCertificate();
|
||||||
|
FDroidApp.repo.fingerprint = Utils.calcFingerprint(localCert);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Once the IP address is known we need to generate a self
|
* Once the IP address is known we need to generate a self
|
||||||
* signed certificate to use for HTTPS that has a CN field set
|
* signed certificate to use for HTTPS that has a CN field set
|
||||||
@ -101,8 +103,14 @@ public class WifiStateChangeService extends Service {
|
|||||||
*/
|
*/
|
||||||
if (Preferences.get().isLocalRepoHttpsEnabled())
|
if (Preferences.get().isLocalRepoHttpsEnabled())
|
||||||
localRepoKeyStore.setupHTTPSCertificate();
|
localRepoKeyStore.setupHTTPSCertificate();
|
||||||
|
|
||||||
|
} catch (LocalRepoKeyStore.InitException e) {
|
||||||
|
Log.e(TAG, "Unable to configure a fingerprint or HTTPS for the local repo: " + e.getMessage());
|
||||||
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
|
}
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
Log.e(TAG, Log.getStackTraceString(e));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package org.fdroid.fdroid.updater;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import org.fdroid.fdroid.FDroidApp;
|
||||||
import org.fdroid.fdroid.Hasher;
|
import org.fdroid.fdroid.Hasher;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.Utils;
|
import org.fdroid.fdroid.Utils;
|
||||||
@ -123,7 +124,17 @@ public class SignedRepoUpdater extends RepoUpdater {
|
|||||||
// Don't worry about checking the status code for 200. If it was a
|
// Don't worry about checking the status code for 200. If it was a
|
||||||
// successful download, then we will have a file ready to use:
|
// successful download, then we will have a file ready to use:
|
||||||
if (indexJar != null && indexJar.exists()) {
|
if (indexJar != null && indexJar.exists()) {
|
||||||
|
|
||||||
|
// Due to a bug in android 5.0 lollipop, the inclusion of BouncyCastle causes
|
||||||
|
// breakage when verifying the signature of the downloaded .jar. For more
|
||||||
|
// details, check out https://gitlab.com/fdroid/fdroidclient/issues/111.
|
||||||
|
try {
|
||||||
|
FDroidApp.disableSpongyCastleOnLollipop();
|
||||||
indexXml = extractIndexFromJar(indexJar);
|
indexXml = extractIndexFromJar(indexJar);
|
||||||
|
} finally {
|
||||||
|
FDroidApp.enableSpongyCastleOnLollipop();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return indexXml;
|
return indexXml;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user