mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 12:19:54 +01:00
Encrypt and save crash reports, send them the next time TorPlugin start
Will currently fail at runtime; requires a public key and a server onion.
This commit is contained in:
@@ -37,6 +37,8 @@ import dagger.Component;
|
||||
})
|
||||
public interface AndroidComponent extends CoreEagerSingletons {
|
||||
|
||||
void inject(CrashReportActivity crashReportActivity);
|
||||
|
||||
void inject(SplashScreenActivity activity);
|
||||
|
||||
void inject(SetupActivity activity);
|
||||
|
||||
@@ -8,7 +8,9 @@ import org.briarproject.api.crypto.SecretKey;
|
||||
import org.briarproject.api.db.DatabaseConfig;
|
||||
import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.reporting.DevConfig;
|
||||
import org.briarproject.api.ui.UiCallback;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -90,6 +92,33 @@ public class AppModule {
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public DevConfig provideDevConfig() {
|
||||
return new DevConfig() {
|
||||
|
||||
// TODO fill in
|
||||
private final byte[] DEV_PUB_KEY = StringUtils.fromHexString("");
|
||||
private final String DEV_ONION = "";
|
||||
private final int DEV_REPORT_PORT = 8080;
|
||||
|
||||
@Override
|
||||
public byte[] getDevPublicKey() {
|
||||
return DEV_PUB_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDevOnionAddress() {
|
||||
return DEV_ONION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDevReportPort() {
|
||||
return DEV_REPORT_PORT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ReferenceManager provideReferenceManager() {
|
||||
|
||||
@@ -2,7 +2,9 @@ package org.briarproject.android;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
@@ -18,12 +20,15 @@ import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.api.reporting.DevReporter;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -36,12 +41,10 @@ import java.util.Scanner;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
|
||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
import static android.content.Intent.ACTION_SEND;
|
||||
import static android.content.Intent.EXTRA_EMAIL;
|
||||
import static android.content.Intent.EXTRA_SUBJECT;
|
||||
import static android.content.Intent.EXTRA_TEXT;
|
||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
|
||||
@@ -59,6 +62,9 @@ public class CrashReportActivity extends AppCompatActivity
|
||||
private LinearLayout status = null;
|
||||
private View progress = null;
|
||||
|
||||
@Inject
|
||||
protected DevReporter reporter;
|
||||
|
||||
private volatile String stack = null;
|
||||
private volatile int pid = -1;
|
||||
private volatile BluetoothAdapter bt = null;
|
||||
@@ -68,6 +74,9 @@ public class CrashReportActivity extends AppCompatActivity
|
||||
super.onCreate(state);
|
||||
setContentView(R.layout.activity_crash);
|
||||
|
||||
((BriarApplication) getApplication()).getApplicationComponent()
|
||||
.inject(this);
|
||||
|
||||
status = (LinearLayout) findViewById(R.id.crash_status);
|
||||
progress = findViewById(R.id.progress_wheel);
|
||||
|
||||
@@ -94,7 +103,20 @@ public class CrashReportActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
share();
|
||||
// TODO Encapsulate the dialog in a re-usable fragment
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.dialog_title_share_crash_report);
|
||||
builder.setMessage(R.string.dialog_message_share_crash_report);
|
||||
builder.setNegativeButton(R.string.cancel_button, null);
|
||||
builder.setPositiveButton(R.string.send,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
saveCrashReport();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
@@ -324,7 +346,7 @@ public class CrashReportActivity extends AppCompatActivity
|
||||
return Character.toUpperCase(first) + s.substring(1);
|
||||
}
|
||||
|
||||
private void share() {
|
||||
private void saveCrashReport() {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (Entry<String, String> e : getStatusMap().entrySet()) {
|
||||
s.append(e.getKey());
|
||||
@@ -332,12 +354,19 @@ public class CrashReportActivity extends AppCompatActivity
|
||||
s.append(e.getValue());
|
||||
s.append("\n\n");
|
||||
}
|
||||
String body = s.toString();
|
||||
Intent i = new Intent(ACTION_SEND);
|
||||
i.setType("message/rfc822");
|
||||
i.putExtra(EXTRA_EMAIL, new String[] { "contact@briarproject.org" });
|
||||
i.putExtra(EXTRA_SUBJECT, "Crash report");
|
||||
i.putExtra(EXTRA_TEXT, body);
|
||||
startActivity(Intent.createChooser(i, "Send to developers"));
|
||||
final String crashReport = s.toString();
|
||||
try {
|
||||
reporter.encryptCrashReportToFile(
|
||||
AndroidUtils.getCrashReportDir(this), crashReport);
|
||||
Toast.makeText(this, R.string.crash_report_saved, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
finish();
|
||||
} catch (FileNotFoundException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, "Error while saving encrypted crash report",
|
||||
e);
|
||||
Toast.makeText(this, R.string.crash_report_not_saved,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,15 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
public class AndroidUtils {
|
||||
|
||||
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
|
||||
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
|
||||
|
||||
private static final String STORED_CRASH_REPORTS = "crash-reports";
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Collection<String> getSupportedArchitectures() {
|
||||
@@ -84,4 +88,8 @@ public class AndroidUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static File getCrashReportDir(Context ctx) {
|
||||
return ctx.getDir(STORED_CRASH_REPORTS, MODE_PRIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.briarproject.api.plugins.BackoffFactory;
|
||||
import org.briarproject.api.plugins.PluginConfig;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.api.reporting.DevReporter;
|
||||
import org.briarproject.api.system.LocationUtils;
|
||||
import org.briarproject.plugins.droidtooth.DroidtoothPluginFactory;
|
||||
import org.briarproject.plugins.tcp.AndroidLanTcpPluginFactory;
|
||||
@@ -31,12 +32,13 @@ public class AndroidPluginsModule {
|
||||
public PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||
AndroidExecutor androidExecutor,
|
||||
SecureRandom random, BackoffFactory backoffFactory, Application app,
|
||||
LocationUtils locationUtils, EventBus eventBus) {
|
||||
LocationUtils locationUtils, DevReporter reporter,
|
||||
EventBus eventBus) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
|
||||
androidExecutor, appContext, random, backoffFactory);
|
||||
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
|
||||
locationUtils, eventBus);
|
||||
locationUtils, reporter, eventBus);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
backoffFactory, appContext);
|
||||
final Collection<DuplexPluginFactory> duplex =
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.freehaven.tor.control.TorControlConnection;
|
||||
import net.sourceforge.jsocks.socks.Socks5Proxy;
|
||||
import net.sourceforge.jsocks.socks.SocksSocket;
|
||||
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
@@ -25,6 +26,7 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.reporting.DevReporter;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.system.LocationUtils;
|
||||
@@ -83,6 +85,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
private final Executor ioExecutor;
|
||||
private final Context appContext;
|
||||
private final LocationUtils locationUtils;
|
||||
private final DevReporter reporter;
|
||||
private final Clock clock;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final String architecture;
|
||||
@@ -104,12 +107,13 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||
|
||||
TorPlugin(Executor ioExecutor, Context appContext,
|
||||
LocationUtils locationUtils, Clock clock,
|
||||
LocationUtils locationUtils, DevReporter reporter, Clock clock,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime, int pollingInterval) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.appContext = appContext;
|
||||
this.locationUtils = locationUtils;
|
||||
this.reporter = reporter;
|
||||
this.clock = clock;
|
||||
this.callback = callback;
|
||||
this.architecture = architecture;
|
||||
@@ -172,13 +176,14 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
String torPath = torFile.getAbsolutePath();
|
||||
String configPath = configFile.getAbsolutePath();
|
||||
String pid = String.valueOf(android.os.Process.myPid());
|
||||
String[] cmd = { torPath, "-f", configPath, OWNER, pid };
|
||||
String[] env = { "HOME=" + torDirectory.getAbsolutePath() };
|
||||
String[] cmd = {torPath, "-f", configPath, OWNER, pid};
|
||||
String[] env = {"HOME=" + torDirectory.getAbsolutePath()};
|
||||
Process torProcess;
|
||||
try {
|
||||
torProcess = Runtime.getRuntime().exec(cmd, env, torDirectory);
|
||||
} catch (SecurityException e1) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e1.toString(), e1);
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e1.toString(), e1);
|
||||
return false;
|
||||
}
|
||||
// Log the process's standard output until it detaches
|
||||
@@ -225,6 +230,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
if (phase != null && phase.contains("PROGRESS=100")) {
|
||||
LOG.info("Tor has already bootstrapped");
|
||||
bootstrapped = true;
|
||||
sendCrashReports();
|
||||
}
|
||||
}
|
||||
// Register to receive network status events
|
||||
@@ -355,6 +361,16 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
}
|
||||
}
|
||||
|
||||
private void sendCrashReports() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
reporter.sendCrashReports(
|
||||
AndroidUtils.getCrashReportDir(appContext), SOCKS_PORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
@@ -420,7 +436,8 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
obs.startWatching();
|
||||
// Use the control connection to update the Tor config
|
||||
List<String> config = Arrays.asList(
|
||||
"HiddenServiceDir " + serviceDirectory.getAbsolutePath(),
|
||||
"HiddenServiceDir " +
|
||||
serviceDirectory.getAbsolutePath(),
|
||||
"HiddenServicePort 80 127.0.0.1:" + port);
|
||||
controlConnection.setConf(config);
|
||||
controlConnection.saveConf();
|
||||
@@ -593,20 +610,24 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
}
|
||||
}
|
||||
|
||||
public void streamStatus(String status, String id, String target) {}
|
||||
public void streamStatus(String status, String id, String target) {
|
||||
}
|
||||
|
||||
public void orConnStatus(String status, String orName) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
||||
}
|
||||
|
||||
public void bandwidthUsed(long read, long written) {}
|
||||
public void bandwidthUsed(long read, long written) {
|
||||
}
|
||||
|
||||
public void newDescriptors(List<String> orList) {}
|
||||
public void newDescriptors(List<String> orList) {
|
||||
}
|
||||
|
||||
public void message(String severity, String msg) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
||||
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
|
||||
bootstrapped = true;
|
||||
sendCrashReports();
|
||||
if (isRunning()) callback.transportEnabled();
|
||||
}
|
||||
}
|
||||
@@ -669,7 +690,7 @@ class TorPlugin implements DuplexPlugin, EventHandler,
|
||||
} else if (blocked) {
|
||||
LOG.info("Disabling network, country is blocked");
|
||||
enableNetwork(false);
|
||||
} else if (wifiOnly & !connectedToWifi){
|
||||
} else if (wifiOnly & !connectedToWifi) {
|
||||
LOG.info("Disabling network due to wifi setting");
|
||||
enableNetwork(false);
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.briarproject.api.event.EventBus;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.api.reporting.DevReporter;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.api.system.LocationUtils;
|
||||
import org.briarproject.system.SystemClock;
|
||||
@@ -28,14 +29,17 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
||||
private final Executor ioExecutor;
|
||||
private final Context appContext;
|
||||
private final LocationUtils locationUtils;
|
||||
private final DevReporter reporter;
|
||||
private final EventBus eventBus;
|
||||
private final Clock clock;
|
||||
|
||||
public TorPluginFactory(Executor ioExecutor, Context appContext,
|
||||
LocationUtils locationUtils, EventBus eventBus) {
|
||||
LocationUtils locationUtils, DevReporter reporter,
|
||||
EventBus eventBus) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.appContext = appContext;
|
||||
this.locationUtils = locationUtils;
|
||||
this.reporter = reporter;
|
||||
this.eventBus = eventBus;
|
||||
clock = new SystemClock();
|
||||
}
|
||||
@@ -68,9 +72,10 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
||||
// Use position-independent executable for SDK >= 16
|
||||
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
|
||||
|
||||
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
|
||||
clock, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME,
|
||||
POLLING_INTERVAL);
|
||||
TorPlugin plugin =
|
||||
new TorPlugin(ioExecutor, appContext, locationUtils, reporter,
|
||||
clock, callback, architecture, MAX_LATENCY,
|
||||
MAX_IDLE_TIME, POLLING_INTERVAL);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user