summaryrefslogtreecommitdiffstats
path: root/src/com/android/nfc
diff options
context:
space:
mode:
authorAndres Morales <anmorales@google.com>2014-11-06 09:05:17 -0800
committerAndres Morales <anmorales@google.com>2014-11-12 08:27:14 -0800
commit8172b1eaa4a1aa57f38b66a57dd1109ad887cd96 (patch)
tree2bb513a2f140c3450d617c4c56dd1a6edc1cb95b /src/com/android/nfc
parenteebaf6f543d8b8983b2b0dce29812d2d2329424f (diff)
downloadandroid_packages_apps_Nfc-8172b1eaa4a1aa57f38b66a57dd1109ad887cd96.tar.gz
android_packages_apps_Nfc-8172b1eaa4a1aa57f38b66a57dd1109ad887cd96.tar.bz2
android_packages_apps_Nfc-8172b1eaa4a1aa57f38b66a57dd1109ad887cd96.zip
Parse auth type from WPS tag
also make parsing more robust and readable Bug: 18255874 Change-Id: Iebe90d0b78654d3e2b515b709bc145a9824560c6
Diffstat (limited to 'src/com/android/nfc')
-rw-r--r--src/com/android/nfc/NfcWifiProtectedSetup.java169
1 files changed, 85 insertions, 84 deletions
diff --git a/src/com/android/nfc/NfcWifiProtectedSetup.java b/src/com/android/nfc/NfcWifiProtectedSetup.java
index 14192488..ad6ef5bf 100644
--- a/src/com/android/nfc/NfcWifiProtectedSetup.java
+++ b/src/com/android/nfc/NfcWifiProtectedSetup.java
@@ -24,8 +24,12 @@ import android.nfc.NdefRecord;
import android.nfc.tech.Ndef;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.BitSet;
public final class NfcWifiProtectedSetup {
@@ -37,13 +41,20 @@ public final class NfcWifiProtectedSetup {
* ID into configuration record for SSID and Network Key in hex.
* Obtained from WFA Wifi Simple Configuration Technical Specification v2.0.2.1.
*/
- private static final String SSID_ID = "1045";
- private static final String NETWORK_KEY_ID = "1027";
+ private static final short CREDENTIAL_FIELD_ID = 0x100E;
+ private static final short SSID_FIELD_ID = 0x1045;
+ private static final short NETWORK_KEY_FIELD_ID = 0x1027;
+ private static final short AUTH_TYPE_FIELD_ID = 0x1003;
+
+ private static final short AUTH_TYPE_EXPECTED_SIZE = 2;
+
+ private static final short AUTH_TYPE_OPEN = 0;
+ private static final short AUTH_TYPE_WPA_PSK = 0x0002;
+ private static final short AUTH_TYPE_WPA_EAP = 0x0008;
+ private static final short AUTH_TYPE_WPA2_EAP = 0x0010;
+ private static final short AUTH_TYPE_WPA2_PSK = 0x0020;
- private static final int SIZE_FIELD_WIDTH = 4;
- private static final int MAX_SSID_SIZE_BYTES = 32;
private static final int MAX_NETWORK_KEY_SIZE_BYTES = 64;
- private static final int HEX_CHARS_PER_BYTE = 2;
private NfcWifiProtectedSetup() {}
@@ -58,7 +69,13 @@ public final class NfcWifiProtectedSetup {
return false;
}
- final WifiConfiguration wifiConfiguration = parse(cachedNdefMessage);
+ final WifiConfiguration wifiConfiguration;
+ try {
+ wifiConfiguration = parse(cachedNdefMessage);
+ } catch (BufferUnderflowException e) {
+ // malformed payload
+ return false;
+ }
if (wifiConfiguration != null &&!UserManager.get(context).hasUserRestriction(
UserManager.DISALLOW_CONFIG_WIFI, UserHandle.CURRENT)) {
@@ -77,99 +94,83 @@ public final class NfcWifiProtectedSetup {
private static WifiConfiguration parse(NdefMessage message) {
NdefRecord[] records = message.getRecords();
- for (int i = 0; i < records.length; ++i) {
- NdefRecord record = records[i];
+ for (NdefRecord record : records) {
if (new String(record.getType()).equals(NFC_TOKEN_MIME_TYPE)) {
- String hexStringPayload = bytesToHex(record.getPayload());
-
- int ssidStringIndex = hexStringPayload.indexOf(SSID_ID);
-
- if (ssidStringIndex > 0) {
- int networkKeyStringIndex = hexStringPayload.indexOf(NETWORK_KEY_ID);
- if (networkKeyStringIndex > 0) {
-
- ssidStringIndex += SSID_ID.length();
- networkKeyStringIndex += NETWORK_KEY_ID.length();
-
- String ssidSize;
- try {
- ssidSize = hexStringPayload.substring(ssidStringIndex,
- ssidStringIndex + SIZE_FIELD_WIDTH);
- } catch(IndexOutOfBoundsException ex) {
- return null;
- }
-
- int ssidSizeBytes = hexStringToInt(ssidSize);
- if (ssidSizeBytes > MAX_SSID_SIZE_BYTES) {
- return null;
- }
-
- String networkKeySize;
- try {
- networkKeySize = hexStringPayload.substring(networkKeyStringIndex,
- networkKeyStringIndex + SIZE_FIELD_WIDTH);
- } catch (IndexOutOfBoundsException ex) {
- return null;
- }
-
- int networkKeySizeBytes = hexStringToInt(networkKeySize);
- if (networkKeySizeBytes > MAX_NETWORK_KEY_SIZE_BYTES) {
- return null;
- }
-
- ssidStringIndex += SIZE_FIELD_WIDTH;
- networkKeyStringIndex += SIZE_FIELD_WIDTH;
-
- String ssid;
- String networkKey;
- try {
- int ssidByteIndex = ssidStringIndex / HEX_CHARS_PER_BYTE;
- ssid = new String(Arrays.copyOfRange(record.getPayload(), ssidByteIndex,
- ssidByteIndex + ssidSizeBytes));
-
- int networkKeyByteIndex = networkKeyStringIndex / HEX_CHARS_PER_BYTE;
- networkKey = new String(Arrays.copyOfRange(record.getPayload(),
- networkKeyByteIndex,
- networkKeyByteIndex + networkKeySizeBytes));
- } catch (ArrayIndexOutOfBoundsException ex) {
- return null;
- }
-
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.preSharedKey = '"' + networkKey + '"';
- configuration.SSID = '"' + ssid + '"';
-
- return configuration;
+ ByteBuffer payload = ByteBuffer.wrap(record.getPayload());
+ while (payload.hasRemaining()) {
+ short fieldId = payload.getShort();
+ short fieldSize = payload.getShort();
+ if (fieldId == CREDENTIAL_FIELD_ID) {
+ return parseCredential(payload, fieldSize);
}
}
}
}
-
return null;
}
- private static int hexStringToInt(String bigEndianHexString) {
- int val = 0;
+ private static WifiConfiguration parseCredential(ByteBuffer payload, short size) {
+ int startPosition = payload.position();
+ WifiConfiguration result = new WifiConfiguration();
+ while (payload.position() < startPosition + size) {
+ short fieldId = payload.getShort();
+ short fieldSize = payload.getShort();
- for (int i = 0; i < bigEndianHexString.length(); ++i) {
- val = (val | Character.digit(bigEndianHexString.charAt(i), 16));
+ // sanity check
+ if (payload.position() + fieldSize > startPosition + size) {
+ return null;
+ }
- if (i < bigEndianHexString.length() - 1) {
- val <<= 4;
+ switch (fieldId) {
+ case SSID_FIELD_ID:
+ byte[] ssid = new byte[fieldSize];
+ payload.get(ssid);
+ result.SSID = new String(ssid);
+ break;
+ case NETWORK_KEY_FIELD_ID:
+ if (fieldSize > MAX_NETWORK_KEY_SIZE_BYTES) {
+ return null;
+ }
+ byte[] networkKey = new byte[fieldSize];
+ payload.get(networkKey);
+ result.preSharedKey = new String(networkKey);
+ break;
+ case AUTH_TYPE_FIELD_ID:
+ if (fieldSize != AUTH_TYPE_EXPECTED_SIZE) {
+ // corrupt data
+ return null;
+ }
+
+ short authType = payload.getShort();
+ populateAllowedKeyManagement(result.allowedKeyManagement, authType);
+ break;
+ default:
+ // unknown / unparsed tag
+ payload.position(payload.position() + fieldSize);
+ break;
}
}
- return val;
+ if (result.preSharedKey != null && result.SSID != null) {
+ return result;
+ }
+
+ return null;
}
- private static String bytesToHex(byte[] bytes) {
- char[] hexChars = new char[bytes.length * 2];
- for ( int j = 0; j < bytes.length; j++) {
- int value = bytes[j] & 0xFF;
- hexChars[j * 2] = Character.forDigit(value >>> 4, 16);
- hexChars[j * 2 + 1] = Character.forDigit(value & 0x0F, 16);
+ private static void populateAllowedKeyManagement(BitSet allowedKeyManagement, short authType) {
+ if (authType == AUTH_TYPE_WPA_PSK) {
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ } else if (authType == AUTH_TYPE_WPA2_PSK) {
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ } else if (authType == (AUTH_TYPE_WPA2_PSK | AUTH_TYPE_WPA_PSK)) {
+ // only WPA_PSK and WPA2_PSK can be mixed together
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK);
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ } else if (authType == AUTH_TYPE_WPA_EAP || authType == AUTH_TYPE_WPA2_EAP) {
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+ } else if (authType == AUTH_TYPE_OPEN) {
+ allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
}
- return new String(hexChars);
}
-
}