mirror of
https://github.com/emanuele-f/PCAPdroid.git
synced 2026-06-28 21:00:51 +08:00
Allow PCAPdroid capture control without prompt via API key
It's now possible to generate an API key to be set in the Intent, allowing to control the PCAPdroid capture without prompt Closes #516
This commit is contained in:
parent
5d82cf10a7
commit
64611f2ed2
@ -106,6 +106,7 @@ public class CaptureCtrl extends AppCompatActivity {
|
||||
|
||||
Intent intent = getIntent();
|
||||
String action = intent.getStringExtra("action");
|
||||
String api_key = intent.getStringExtra("api_key");
|
||||
|
||||
if(action == null) {
|
||||
Log.e(TAG, "no action provided");
|
||||
@ -118,6 +119,17 @@ public class CaptureCtrl extends AppCompatActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
if(api_key != null) {
|
||||
// authenticate via API key
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String my_key = Prefs.getApiKey(prefs);
|
||||
|
||||
if (!my_key.isEmpty() && my_key.equals(api_key)) {
|
||||
processRequest(intent, action);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a control permission rule was set
|
||||
mPermissions = PCAPdroid.getInstance().getCtrlPermissions();
|
||||
AppDescriptor app = getCallingApp();
|
||||
|
||||
@ -132,6 +132,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
|
||||
public static final String PAID_FEATURES_URL = DOCS_URL + "/paid_features";
|
||||
public static final String FIREWALL_DOCS_URL = PAID_FEATURES_URL + "#51-firewall";
|
||||
public static final String MALWARE_DETECTION_DOCS_URL = PAID_FEATURES_URL + "#52-malware-detection";
|
||||
public static final String API_DOCS_URL = GITHUB_PROJECT_URL + "/blob/master/docs/app_api.md";
|
||||
public static final String PCAPNG_DOCS_URL = PAID_FEATURES_URL + "#53-pcapng-format";
|
||||
|
||||
private final ActivityResultLauncher<Intent> sslkeyfileExportLauncher =
|
||||
|
||||
@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
package com.emanuelef.remote_capture.activities.prefs;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
@ -28,21 +31,31 @@ import android.widget.AbsListView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.view.MenuProvider;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.emanuelef.remote_capture.PCAPdroid;
|
||||
import com.emanuelef.remote_capture.R;
|
||||
import com.emanuelef.remote_capture.Utils;
|
||||
import com.emanuelef.remote_capture.activities.BaseActivity;
|
||||
import com.emanuelef.remote_capture.activities.MainActivity;
|
||||
import com.emanuelef.remote_capture.adapters.CtrlPermissionsAdapter;
|
||||
import com.emanuelef.remote_capture.model.CtrlPermissions;
|
||||
import com.emanuelef.remote_capture.model.Prefs;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
|
||||
public class EditCtrlPermissions extends BaseActivity {
|
||||
public class EditCtrlPermissions extends BaseActivity implements MenuProvider {
|
||||
private static final String TAG = "EditCtrlPermissions";
|
||||
private TextView mEmptyText;
|
||||
private CtrlPermissionsAdapter mAdapter;
|
||||
private ListView mListView;
|
||||
private CtrlPermissions mPermissions;
|
||||
private MenuItem mShowApiKey;
|
||||
private final ArrayList<CtrlPermissions.Rule> mSelected = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
@ -51,9 +64,11 @@ public class EditCtrlPermissions extends BaseActivity {
|
||||
|
||||
setTitle(R.string.control_permissions);
|
||||
setContentView(R.layout.simple_list_activity);
|
||||
addMenuProvider(this);
|
||||
|
||||
findViewById(R.id.simple_list).setFitsSystemWindows(true);
|
||||
mEmptyText = findViewById(R.id.list_empty);
|
||||
mEmptyText.setText(R.string.no_permissions_set_info);
|
||||
mListView = findViewById(R.id.listview);
|
||||
|
||||
mPermissions = PCAPdroid.getInstance().getCtrlPermissions();
|
||||
@ -126,7 +141,81 @@ public class EditCtrlPermissions extends BaseActivity {
|
||||
recheckListSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.ctrl_permissions_menu, menu);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mShowApiKey = menu.findItem(R.id.show_api_key);
|
||||
|
||||
if (Prefs.getApiKey(prefs).isEmpty())
|
||||
mShowApiKey.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemSelected(@NonNull MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
if(id == R.id.user_guide) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(MainActivity.API_DOCS_URL));
|
||||
Utils.startActivity(this, browserIntent);
|
||||
return true;
|
||||
} else if (id == R.id.generate_api_key) {
|
||||
generateApiKey(false);
|
||||
return true;
|
||||
} else if (id == R.id.show_api_key) {
|
||||
showApiKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recheckListSize() {
|
||||
mEmptyText.setVisibility((mAdapter.getCount() == 0) ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void generateApiKey(boolean confirmOverwrite) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
if (!confirmOverwrite && !Prefs.getApiKey(prefs).isEmpty()) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.warning)
|
||||
.setMessage(R.string.api_key_discard_confirm)
|
||||
.setPositiveButton(R.string.ok, (dialog, whichButton) -> generateApiKey(true))
|
||||
.setNegativeButton(R.string.cancel_action, (dialog, whichButton) -> {})
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
final String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
final int key_length = 32;
|
||||
SecureRandom random = new SecureRandom();
|
||||
StringBuilder apiKey = new StringBuilder(key_length);
|
||||
for (int i = 0; i < key_length; i++) {
|
||||
int index = random.nextInt(chars.length());
|
||||
apiKey.append(chars.charAt(index));
|
||||
}
|
||||
|
||||
prefs.edit()
|
||||
.putString(Prefs.PREF_API_KEY, apiKey.toString())
|
||||
.apply();
|
||||
|
||||
if (mShowApiKey != null)
|
||||
mShowApiKey.setVisible(true);
|
||||
showApiKey();
|
||||
}
|
||||
|
||||
private void showApiKey() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String key = Prefs.getApiKey(prefs);
|
||||
if (key.isEmpty())
|
||||
return;
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.api_key)
|
||||
.setMessage(key)
|
||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {})
|
||||
.setNeutralButton(R.string.copy_to_clipboard, (dialogInterface, i) ->
|
||||
Utils.copyToClipboard(this, key)).show();
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,14 +461,11 @@ public class SettingsActivity extends BaseActivity implements PreferenceFragment
|
||||
mIpMode = requirePreference(Prefs.PREF_IP_MODE);
|
||||
|
||||
Preference ctrlPerm = requirePreference("control_permissions");
|
||||
if(!PCAPdroid.getInstance().getCtrlPermissions().hasRules())
|
||||
ctrlPerm.setVisible(false);
|
||||
else
|
||||
ctrlPerm.setOnPreferenceClickListener(preference -> {
|
||||
Intent intent = new Intent(requireContext(), EditCtrlPermissions.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
ctrlPerm.setOnPreferenceClickListener(preference -> {
|
||||
Intent intent = new Intent(requireContext(), EditCtrlPermissions.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void rootCaptureHideShow(boolean enabled) {
|
||||
|
||||
@ -110,6 +110,7 @@ public class Prefs {
|
||||
public static final String PREF_PCAPNG_ENABLED = "pcapng_format";
|
||||
public static final String PREF_RESTART_ON_DISCONNECT = "restart_on_disconnect";
|
||||
public static final String PREF_IGNORED_MITM_VERSION = "ignored_mitm_version";
|
||||
public static final String PREF_API_KEY = "api_key";
|
||||
|
||||
public enum DumpMode {
|
||||
NONE,
|
||||
@ -238,6 +239,7 @@ public class Prefs {
|
||||
public static String getDnsServerV4(SharedPreferences p) { return(p.getString(PREF_DNS_SERVER_V4, "1.1.1.1")); }
|
||||
public static String getDnsServerV6(SharedPreferences p) { return(p.getString(PREF_DNS_SERVER_V6, "2606:4700:4700::1111")); }
|
||||
public static boolean isIgnoredMitmVersion(SharedPreferences p, String v) { return p.getString(PREF_IGNORED_MITM_VERSION, "").equals(v); }
|
||||
public static String getApiKey(SharedPreferences p) { return(p.getString(PREF_API_KEY, "")); }
|
||||
|
||||
// Gets a StringSet from the prefs
|
||||
// The preference should either be a StringSet or a String
|
||||
|
||||
24
app/src/main/res/menu/ctrl_permissions_menu.xml
Normal file
24
app/src/main/res/menu/ctrl_permissions_menu.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/user_guide"
|
||||
android:title="@string/user_guide"
|
||||
android:orderInCategory="10"
|
||||
android:icon="@drawable/ic_book"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/show_api_key"
|
||||
android:title="@string/show_api_key"
|
||||
android:orderInCategory="20"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/generate_api_key"
|
||||
android:title="@string/generate_api_key"
|
||||
android:orderInCategory="20"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
@ -217,6 +217,11 @@
|
||||
<string name="control_permissions">Control permissions</string>
|
||||
<string name="control_permissions_summary">Check which apps are allowed to control the PCAPdroid capture</string>
|
||||
<string name="control_permissions_item">%1$s: %2$s</string>
|
||||
<string name="no_permissions_set_info">No permissions set. Invoke PCAPdroid via StartActivityForResult to show the permissions prompt</string>
|
||||
<string name="generate_api_key">Generate API key</string>
|
||||
<string name="show_api_key">Show API key</string>
|
||||
<string name="api_key">API key</string>
|
||||
<string name="api_key_discard_confirm">Do you really want to discard the current API key and generate a new one?</string>
|
||||
<string name="country">Country</string>
|
||||
<string name="asn">ASN</string>
|
||||
<string name="country_val">Country: %1$s</string>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user