binder: Implement Set enterprise network params
Implement all the enterprise network params setter
binder methods.
The eap method setter needs to have a string lookup to ensure
that the device supports the corresponding EAP type.
While there,
Add helper functions to set string/byte array fields in |wpa_ssid|
structure and refactor existing binder calls.
BUG: 1252274
Change-Id: Id669eb7aecda23a3636248ce9c4772b33ab34aa5
TEST: Ran existing tests.
TEST: Adding tests under |wpa_supplicant_binder_test|.
diff --git a/wpa_supplicant/binder/network.cpp b/wpa_supplicant/binder/network.cpp
index 2fb5ae0..99b8347 100644
--- a/wpa_supplicant/binder/network.cpp
+++ b/wpa_supplicant/binder/network.cpp
@@ -33,6 +33,19 @@
(fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_NONE |
fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_TKIP |
fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_CCMP);
+
+constexpr int kEapMethodMax =
+ fi::w1::wpa_supplicant::INetwork::EAP_METHOD_WFA_UNAUTH_TLS + 1;
+constexpr int kEapMethodMin = fi::w1::wpa_supplicant::INetwork::EAP_METHOD_PEAP;
+constexpr char const *kEapMethodStrings[kEapMethodMax] = {
+ "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
+
+constexpr int kEapPhase2MethodMax =
+ fi::w1::wpa_supplicant::INetwork::EAP_PHASE2_METHOD_GTC + 1;
+constexpr int kEapPhase2MethodMin =
+ fi::w1::wpa_supplicant::INetwork::EAP_PHASE2_METHOD_NONE;
+constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
+ "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
} // namespace
namespace wpa_supplicant_binder {
@@ -95,26 +108,14 @@
android::binder::Status::EX_ILLEGAL_ARGUMENT,
error_msg.c_str());
}
- // Free any existing ssid string.
- if (wpa_ssid->ssid) {
- os_free(wpa_ssid);
- }
- // This array needs to be a null terminated!.
- wpa_ssid->ssid = (uint8_t *)os_malloc(ssid.size() + 1);
- if (!wpa_ssid->ssid) {
- return android::binder::Status::fromExceptionCode(
- ERROR_GENERIC, "Memory allocation failed.");
- }
- os_memcpy(wpa_ssid->ssid, ssid.data(), ssid.size());
- wpa_ssid->ssid[ssid.size()] = '\0';
- wpa_ssid->ssid_len = ssid.size();
- if (wpa_ssid->passphrase) {
+
+ android::binder::Status status = setByteArrayKeyFieldAndResetState(
+ ssid.data(), ssid.size(), &(wpa_ssid->ssid), &(wpa_ssid->ssid_len),
+ "ssid");
+ if (status.isOk() && wpa_ssid->passphrase) {
wpa_config_update_psk(wpa_ssid);
}
- wpa_hexdump_ascii(
- MSG_MSGDUMP, "SSID", wpa_ssid->ssid, wpa_ssid->ssid_len);
- resetInternalStateAfterParamsUpdate();
- return android::binder::Status::ok();
+ return status;
}
android::binder::Status Network::SetBSSID(const std::vector<uint8_t> &bssid)
@@ -273,20 +274,12 @@
// Flag to indicate if raw psk is calculated or not using
// |wpa_config_update_psk|. Deferred if ssid not already set.
wpa_ssid->psk_set = 0;
- str_clear_free(wpa_ssid->passphrase);
- wpa_ssid->passphrase = dup_binstr(psk.c_str(), psk.size());
- if (!wpa_ssid->passphrase) {
- return android::binder::Status::fromExceptionCode(
- ERROR_GENERIC, "Memory allocation failed.");
- }
- if (wpa_ssid->ssid_len) {
+ android::binder::Status status = setStringKeyFieldAndResetState(
+ psk.data(), &(wpa_ssid->passphrase), "psk passphrase");
+ if (status.isOk() && wpa_ssid->ssid_len) {
wpa_config_update_psk(wpa_ssid);
}
- wpa_hexdump_ascii_key(
- MSG_MSGDUMP, "PSK (ASCII passphrase)", (u8 *)wpa_ssid->passphrase,
- psk.size());
- resetInternalStateAfterParamsUpdate();
- return android::binder::Status::ok();
+ return status;
}
android::binder::Status
@@ -354,7 +347,59 @@
{
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
+ int retrieved_vendor, retrieved_method;
+ if (method < kEapMethodMin || method >= kEapMethodMax) {
+ const std::string error_msg =
+ "Invalid EAP method: " + std::to_string(method) + ".";
+ return android::binder::Status::fromExceptionCode(
+ android::binder::Status::EX_ILLEGAL_ARGUMENT,
+ error_msg.c_str());
+ }
+ const char *method_str = kEapMethodStrings[method];
+ // This string lookup is needed to check if the device supports the
+ // corresponding EAP type.
+ retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
+ if (retrieved_vendor == EAP_VENDOR_IETF &&
+ retrieved_method == EAP_TYPE_NONE) {
+ const std::string error_msg = "Cannot get EAP method type: " +
+ std::to_string(method) + ".";
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, error_msg.c_str());
+ }
+
+ if (wpa_ssid->eap.eap_methods) {
+ os_free(wpa_ssid->eap.eap_methods);
+ }
+ // wpa_supplicant can support setting multiple eap methods for each
+ // network. But, this is not really used by Android. So, just adding
+ // support for setting one EAP method for each network. The additional
+ // |eap_method_type| member in the array is used to indicate the end
+ // of list.
+ wpa_ssid->eap.eap_methods =
+ (eap_method_type *)os_malloc(sizeof(eap_method_type) * 2);
+ if (!wpa_ssid->eap.eap_methods) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "Memory allocation failed.");
+ }
+ wpa_ssid->eap.eap_methods[0].vendor = retrieved_vendor;
+ wpa_ssid->eap.eap_methods[0].method = retrieved_method;
+ wpa_ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
+ wpa_ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
+
+ wpa_ssid->leap = 0;
+ wpa_ssid->non_leap = 0;
+ if (retrieved_vendor == EAP_VENDOR_IETF &&
+ retrieved_method == EAP_TYPE_LEAP) {
+ wpa_ssid->leap++;
+ } else {
+ wpa_ssid->non_leap++;
+ }
+
+ wpa_hexdump(
+ MSG_MSGDUMP, "eap methods", (u8 *)wpa_ssid->eap.eap_methods,
+ sizeof(eap_method_type) * 2);
+ resetInternalStateAfterParamsUpdate();
return android::binder::Status::ok();
}
@@ -363,7 +408,16 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ if (method < kEapPhase2MethodMin || method >= kEapMethodMax) {
+ const std::string error_msg = "Invalid EAP Phase2 method: " +
+ std::to_string(method) + ".";
+ return android::binder::Status::fromExceptionCode(
+ android::binder::Status::EX_ILLEGAL_ARGUMENT,
+ error_msg.c_str());
+ }
+ return setStringFieldAndResetState(
+ kEapPhase2MethodStrings[method], &(wpa_ssid->eap.phase2),
+ "eap phase2");
}
android::binder::Status
@@ -372,7 +426,9 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setByteArrayFieldAndResetState(
+ identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+ &(wpa_ssid->eap.identity_len), "eap identity");
}
android::binder::Status
@@ -381,7 +437,10 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setByteArrayFieldAndResetState(
+ identity.data(), identity.size(),
+ &(wpa_ssid->eap.anonymous_identity),
+ &(wpa_ssid->eap.anonymous_identity_len), "eap anonymous_identity");
}
android::binder::Status
@@ -390,7 +449,14 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ android::binder::Status status = setByteArrayKeyFieldAndResetState(
+ password.data(), password.size(), &(wpa_ssid->eap.password),
+ &(wpa_ssid->eap.password_len), "eap password");
+ if (status.isOk()) {
+ wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
+ wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
+ }
+ return status;
}
android::binder::Status Network::SetEapCACert(const std::string &path)
@@ -398,7 +464,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.ca_cert), "eap ca_cert");
}
android::binder::Status Network::SetEapCAPath(const std::string &path)
@@ -406,7 +473,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.ca_path), "eap ca_path");
}
android::binder::Status Network::SetEapClientCert(const std::string &path)
@@ -414,7 +482,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.client_cert), "eap client_cert");
}
android::binder::Status Network::SetEapPrivateKey(const std::string &path)
@@ -422,7 +491,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ path.c_str(), &(wpa_ssid->eap.private_key), "eap private_key");
}
android::binder::Status Network::SetEapSubjectMatch(const std::string &match)
@@ -431,7 +501,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.subject_match), "eap subject_match");
}
android::binder::Status Network::SetEapAltSubjectMatch(const std::string &match)
@@ -439,7 +510,9 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.altsubject_match),
+ "eap altsubject_match");
}
android::binder::Status Network::SetEapEngine(bool enable)
@@ -447,6 +520,7 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
+ wpa_ssid->eap.engine = enable ? 1 : 0;
return android::binder::Status::ok();
}
@@ -456,6 +530,8 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
+ return setStringFieldAndResetState(
+ id.c_str(), &(wpa_ssid->eap.engine_id), "eap engine_id");
return android::binder::Status::ok();
}
@@ -466,7 +542,9 @@
struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
RETURN_IF_NETWORK_INVALID(wpa_ssid);
- return android::binder::Status::ok();
+ return setStringFieldAndResetState(
+ match.c_str(), &(wpa_ssid->eap.domain_suffix_match),
+ "eap domain_suffix_match");
}
android::binder::Status Network::GetSSID(std::vector<uint8_t> *ssid)
@@ -707,4 +785,117 @@
eapol_sm_invalidate_cached_session(wpa_s->eapol);
}
}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::binder::Status Network::setStringFieldAndResetState(
+ const char *value, uint8_t **to_update_field, const char *hexdump_prefix)
+{
+ return setStringFieldAndResetState(
+ value, (char **)to_update_field, hexdump_prefix);
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::binder::Status Network::setStringFieldAndResetState(
+ const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+ int value_len = strlen(value);
+ if (*to_update_field) {
+ os_free(*to_update_field);
+ }
+ *to_update_field = dup_binstr(value, value_len);
+ if (!(*to_update_field)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "Memory allocation failed.");
+ }
+ wpa_hexdump_ascii(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+ resetInternalStateAfterParamsUpdate();
+ return android::binder::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string key field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::binder::Status Network::setStringKeyFieldAndResetState(
+ const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+ int value_len = strlen(value);
+ if (*to_update_field) {
+ str_clear_free(*to_update_field);
+ }
+ *to_update_field = dup_binstr(value, value_len);
+ if (!(*to_update_field)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "Memory allocation failed.");
+ }
+ wpa_hexdump_ascii_key(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+ resetInternalStateAfterParamsUpdate();
+ return android::binder::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::binder::Status Network::setByteArrayFieldAndResetState(
+ const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+ size_t *to_update_field_len, const char *hexdump_prefix)
+{
+ if (*to_update_field) {
+ os_free(*to_update_field);
+ }
+ *to_update_field = (uint8_t *)os_malloc(value_len);
+ if (!(*to_update_field)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "Memory allocation failed.");
+ }
+ os_memcpy(*to_update_field, value, value_len);
+ *to_update_field_len = value_len;
+
+ wpa_hexdump_ascii(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+ *to_update_field_len);
+ resetInternalStateAfterParamsUpdate();
+ return android::binder::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string key field with a corresponding
+ * length field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::binder::Status Network::setByteArrayKeyFieldAndResetState(
+ const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+ size_t *to_update_field_len, const char *hexdump_prefix)
+{
+ if (*to_update_field) {
+ bin_clear_free(*to_update_field, *to_update_field_len);
+ }
+ *to_update_field = (uint8_t *)os_malloc(value_len);
+ if (!(*to_update_field)) {
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_GENERIC, "Memory allocation failed.");
+ }
+ os_memcpy(*to_update_field, value, value_len);
+ *to_update_field_len = value_len;
+
+ wpa_hexdump_ascii_key(
+ MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+ *to_update_field_len);
+ resetInternalStateAfterParamsUpdate();
+ return android::binder::Status::ok();
+}
+
} // namespace wpa_supplicant_binder
diff --git a/wpa_supplicant/binder/network.h b/wpa_supplicant/binder/network.h
index 7def762..bfa5c8d 100644
--- a/wpa_supplicant/binder/network.h
+++ b/wpa_supplicant/binder/network.h
@@ -21,6 +21,7 @@
#include "wpa_supplicant_i.h"
#include "notify.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
#include "rsn_supp/wpa.h"
}
@@ -110,6 +111,23 @@
struct wpa_supplicant *retrieveIfacePtr();
int isPskPassphraseValid(const std::string &psk);
void resetInternalStateAfterParamsUpdate();
+ android::binder::Status setStringFieldAndResetState(
+ const char *value, uint8_t **to_update_field,
+ const char *hexdump_prefix);
+ android::binder::Status setStringFieldAndResetState(
+ const char *value, char **to_update_field,
+ const char *hexdump_prefix);
+ android::binder::Status setStringKeyFieldAndResetState(
+ const char *value, char **to_update_field,
+ const char *hexdump_prefix);
+ android::binder::Status setByteArrayFieldAndResetState(
+ const uint8_t *value, const size_t value_len,
+ uint8_t **to_update_field, size_t *to_update_field_len,
+ const char *hexdump_prefix);
+ android::binder::Status setByteArrayKeyFieldAndResetState(
+ const uint8_t *value, const size_t value_len,
+ uint8_t **to_update_field, size_t *to_update_field_len,
+ const char *hexdump_prefix);
// Reference to the global wpa_struct. This is assumed to be valid for
// the lifetime of the process.