wpadebug: Add a Wi-Fi debugging app for Android

This tool can be used to debug Wi-Fi functionality on Android both
through the Android framework and through direct access to
wpa_supplicant.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-05-03 00:52:32 +03:00
parent 741ed9fc25
commit 4bb4f7cd00
7 changed files with 516 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="w1.fi.wpadebug"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<application android:label="wpadebug">
<activity android:name="w1.fi.wpadebug.MainActivity"
android:label="wpadebug">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="w1.fi.wpadebug.DisplayMessageActivity"
android:label="Operation result"
android:parentActivityName="w1.fi.wpadebug.MainActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.wfa.wsc" />
</intent-filter>
</activity>
</application>
</manifest>

56
wpadebug/README Normal file
View File

@ -0,0 +1,56 @@
wpadebug - wpa_supplicant and Wi-Fi debugging app for Android
Copyright (c) 2013, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
advertisement clause removed). See the top level README for detailed
license text.
If you are submitting changes to the project, please see CONTRIBUTIONS
file for more instructions.
NOTE! This Android app is for debugging and testing purposes only. It is
not supposed to be installed on a production use device and doing so may
result in complete loss of security protections on the device.
Build
-----
- Install Android SDK and build tools
- update project target if desired; for example:
android list targets
android update project --target 1 --path $PWD
- run: ant debug
Installation (with adb over USB)
------------
adb install bin/wpadebug-debug.apk
NOTE: Following steps enable any app on the system to get root access!
This is not suitable for any production use. This is needed for direct
wpa_supplicant access and some networking operating in general. You can
still use rest of the wpadebug app without doing this, but those
functions will not work unless this step part of installation is
done. It should be obvious that these steps require a rooted device. In
addition, if you do not understand what the following commands do,
please do not run them.
adb root
adb remount
adb shell chmod 6755 /system/bin/mksh-su
Uninstallation
--------------
adb root
adb remount
adb shell rm /system/bin/mksh-su
adb uninstall w1.fi.wpadebug

17
wpadebug/build.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="wpadebug" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>

View File

@ -0,0 +1,2 @@
# Project target.
target=android-17

View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Framework commands"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="WifiManager"
android:onClick="wifiManagerInfo"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="WifiInfo"
android:onClick="wifiInfo"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Networks"
android:onClick="wifiConfiguredNetworks"
/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="wpa_supplicant commands"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="status"
android:onClick="wpaStatus"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PMKSA"
android:onClick="wpaPmksa"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="networks"
android:onClick="wpaListNetworks"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="creds"
android:onClick="wpaListCreds"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="scanres"
android:onClick="wpaScanResults"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="log:info"
android:onClick="wpaLogLevelInfo"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="log:debug"
android:onClick="wpaLogLevelDebug"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="log:excessive"
android:onClick="wpaLogLevelExcessive"
/>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<EditText android:id="@+id/edit_cmd"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="wpa_cli command"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Run"
android:onClick="runWpaCliCmd"
/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Shell commands"
/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="id"
android:onClick="runId"
/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,88 @@
/*
* wpadebug - wpa_supplicant and Wi-Fi debugging app for Android
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
package w1.fi.wpadebug;
import android.app.Activity;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.MenuItem;
import android.content.Intent;
import android.widget.TextView;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
public class DisplayMessageActivity extends Activity
{
private static final String TAG = "wpadebug";
String byteArrayHex(byte[] a) {
StringBuilder sb = new StringBuilder();
for (byte b: a)
sb.append(String.format("%02x", b));
return sb.toString();
}
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
// Get the message from the intent
Intent intent = getIntent();
String action = intent.getAction();
Log.d(TAG, "onCreate: action=" + action);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
return; // handled in onResume()
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = new TextView(this);
textView.setText(message);
textView.setMovementMethod(new ScrollingMovementMethod());
setContentView(textView);
}
@Override
public void onResume()
{
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
Log.d(TAG, "onResume: action=" + action);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Log.d(TAG, "onResume - NDEF discovered");
Parcelable[] raw = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (raw != null) {
String txt = "NDEF message count: " + raw.length;
Log.d(TAG, txt);
NdefMessage[] msgs = new NdefMessage[raw.length];
for (int i = 0; i < raw.length; i++) {
msgs[i] = (NdefMessage) raw[i];
NdefRecord rec = msgs[i].getRecords()[0];
Log.d(TAG, "MIME type: " + rec.toMimeType());
byte[] a = rec.getPayload();
Log.d(TAG, "NDEF record: " + byteArrayHex(a));
txt += "\nMessage[" + rec.toMimeType() + "]: " +
byteArrayHex(a);
}
TextView textView = new TextView(this);
textView.setText(txt);
textView.setMovementMethod(new ScrollingMovementMethod());
setContentView(textView);
}
}
}
}

View File

@ -0,0 +1,183 @@
/*
* wpadebug - wpa_supplicant and Wi-Fi debugging app for Android
* Copyright (c) 2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
package w1.fi.wpadebug;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
import android.content.Context;
import android.content.DialogInterface;
import android.widget.EditText;
import android.util.Log;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiConfiguration;
public class MainActivity extends Activity
{
public final static String EXTRA_MESSAGE = "w1.fi.wpadebug.MESSAGE";
private static final String TAG = "wpadebug";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void runId(View view)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
String message = run("/system/bin/id");
if (message == null)
return;
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
public void runWpaCliCmd(View view)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_cmd);
String cmd = editText.getText().toString();
if (cmd.trim().length() == 0) {
show_alert("wpa_cli command", "Invalid command");
return;
}
wpaCmd(view, cmd);
}
public void wpaStatus(View view)
{
wpaCmd(view, "STATUS");
}
public void wpaPmksa(View view)
{
wpaCmd(view, "PMKSA");
}
public void wpaScanResults(View view)
{
wpaCmd(view, "SCAN_RESULTS");
}
public void wpaListNetworks(View view)
{
wpaCmd(view, "LIST_NETWORKS");
}
public void wpaListCreds(View view)
{
wpaCmd(view, "LIST_CREDS");
}
public void wpaLogLevelInfo(View view)
{
wpaCmd(view, "LOG_LEVEL INFO 1");
}
public void wpaLogLevelDebug(View view)
{
wpaCmd(view, "LOG_LEVEL DEBUG 1");
}
public void wpaLogLevelExcessive(View view)
{
wpaCmd(view, "LOG_LEVEL EXCESSIVE 1");
}
private void wpaCmd(View view, String cmd)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
String message = run("wpa_cli " + cmd);
if (message == null)
return;
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
private String run(String cmd)
{
try {
Log.d(TAG, "Running external process: " + cmd);
Process proc = Runtime.getRuntime().exec(new String[]{"/system/bin/mksh-su", "-c", cmd});
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
StringBuffer output = new StringBuffer();
int read;
char[] buffer = new char[1024];
while ((read = reader.read(buffer)) > 0)
output.append(buffer, 0, read);
reader.close();
proc.waitFor();
Log.d(TAG, "External process completed - exitValue " +
proc.exitValue());
return output.toString();
} catch (IOException e) {
show_alert("Could not run external program",
"Execution of an external program failed. " +
"Maybe mksh-su was not installed.");
return null;
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private void show_alert(String title, String message)
{
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(title);
alert.setMessage(message);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id)
{
}
});
alert.create().show();
}
public void wifiManagerInfo(View view)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
String message = "WifiState: " + manager.getWifiState() + "\n" +
"WifiEnabled: " + manager.isWifiEnabled() + "\n" +
"pingSupplicant: " + manager.pingSupplicant() + "\n" +
"DhcpInfo: " + manager.getDhcpInfo().toString() + "\n";
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
public void wifiInfo(View view)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wifi = manager.getConnectionInfo();
String message = wifi.toString() + "\n" + wifi.getSupplicantState();
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
public void wifiConfiguredNetworks(View view)
{
Intent intent = new Intent(this, DisplayMessageActivity.class);
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
StringBuilder sb = new StringBuilder();
for (WifiConfiguration n: manager.getConfiguredNetworks())
sb.append(n.toString() + "\n");
intent.putExtra(EXTRA_MESSAGE, sb.toString());
startActivity(intent);
}
}