shill: Add support for connecting to WPA+802.1x networks
This includes supporting EAP-TTLS and EAP-PEAP networks.
Also, also add a "connectability" check for 802.1x networks which
checks if there are sufficient and necessary EAP parameters to attempt
a connection.
BUG=chromium-os:20901, chromium-os:23466
TEST=2 new unit tests + 3 new autotests pass (019CheckWPA_1x_AES,
072CheckWPA_1x_PEAP and 073CheckWPA_1x_TTLS)
Change-Id: I46c1886d8fd901c1f95387c984975f2aac89b28e
Reviewed-on: https://gerrit.chromium.org/gerrit/13063
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Gaurav Shah <gauravsh@chromium.org>
Tested-by: Gaurav Shah <gauravsh@chromium.org>
diff --git a/wifi_service.cc b/wifi_service.cc
index f0ee9e5..175ba57 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -5,6 +5,7 @@
#include "shill/wifi_service.h"
#include <string>
+#include <utility>
#include <base/logging.h>
#include <base/stringprintf.h>
@@ -84,8 +85,8 @@
// TODO(quiche): determine if it is okay to set EAP.KeyManagement for
// a service that is not 802.1x.
if (security_ == flimflam::kSecurity8021x) {
- NOTIMPLEMENTED();
- // XXX needs_passpharse_ = false ?
+ // Passphrases are not mandatory for 802.1X.
+ need_passphrase_ = false;
} else if (security_ == flimflam::kSecurityPsk) {
SetEAPKeyManagement("WPA-PSK");
} else if (security_ == flimflam::kSecurityRsn) {
@@ -97,7 +98,7 @@
} else if (security_ == flimflam::kSecurityNone) {
SetEAPKeyManagement("NONE");
} else {
- LOG(ERROR) << "unsupported security method " << security_;
+ LOG(ERROR) << "Unsupported security method " << security_;
}
// Until we know better (at Profile load time), use the generic name.
@@ -128,7 +129,7 @@
}
void WiFiService::Connect(Error */*error*/) {
- LOG(INFO) << __func__;
+ LOG(INFO) << "In " << __func__ << "():";
// Defer handling, since dbus-c++ does not permit us to send an
// outbound request while processing an inbound one.
dispatcher()->PostTask(
@@ -341,7 +342,10 @@
append_uint32(WiFiEndpoint::ModeStringToUint(mode_));
if (security_ == flimflam::kSecurity8021x) {
- NOTIMPLEMENTED();
+ // If EAP key management is not set, set to a default.
+ if (GetEAPKeyManagement().empty())
+ SetEAPKeyManagement("WPA-EAP");
+ Populate8021xProperties(¶ms);
} else if (security_ == flimflam::kSecurityPsk) {
const string psk_proto = StringPrintf("%s %s",
wpa_supplicant::kSecurityModeWPA,
@@ -378,7 +382,7 @@
LOG(ERROR) << "Can't connect. Unsupported security method " << security_;
}
- params[wpa_supplicant::kPropertyKeyManagement].writer().
+ params[wpa_supplicant::kNetworkPropertyEapKeyManagement].writer().
append_string(key_management().c_str());
// See note in dbus_adaptor.cc on why we need to use a local.
@@ -397,19 +401,21 @@
}
void WiFiService::UpdateConnectable() {
+ bool is_connectable = false;
if (security_ == flimflam::kSecurityNone) {
DCHECK(passphrase_.empty());
need_passphrase_ = false;
+ is_connectable = true;
} else if (security_ == flimflam::kSecurityWep ||
security_ == flimflam::kSecurityWpa ||
security_ == flimflam::kSecurityPsk ||
security_ == flimflam::kSecurityRsn) {
need_passphrase_ = passphrase_.empty();
- } else {
- // TODO(quiche): Handle connectability for 802.1x. (crosbug.com/23466)
- need_passphrase_ = true;
+ is_connectable = !need_passphrase_;
+ } else if (security_ == flimflam::kSecurity8021x) {
+ is_connectable = Is8021xConnectable();
}
- set_connectable(!need_passphrase_);
+ set_connectable(is_connectable);
}
// static
@@ -608,4 +614,47 @@
security.c_str()));
}
+void WiFiService::set_eap(const EapCredentials &eap) {
+ Service::set_eap(eap);
+ UpdateConnectable();
+}
+
+void WiFiService::Populate8021xProperties(
+ std::map<string, DBus::Variant> *params) {
+ typedef std::pair<const char *, const char *> KeyVal;
+ KeyVal propertyvals[] = {
+ KeyVal(wpa_supplicant::kNetworkPropertyEapIdentity, eap().identity.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapEap, eap().eap.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapInnerEap,
+ eap().inner_eap.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapAnonymousIdentity,
+ eap().anonymous_identity.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapClientCert,
+ eap().client_cert.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapPrivateKey,
+ eap().private_key.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapPrivateKeyPassword,
+ eap().private_key_password.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapCaCert, eap().ca_cert.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapCaPassword,
+ eap().password.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapCertId, eap().cert_id.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapKeyId, eap().key_id.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapCaCertId,
+ eap().ca_cert_id.c_str()),
+ KeyVal(wpa_supplicant::kNetworkPropertyEapPin, eap().pin.c_str()),
+ // TODO(gauravsh): Support getting CA certificates out of the NSS certdb.
+ // crosbug.com/25663
+ KeyVal(wpa_supplicant::kNetworkPropertyCaPath, wpa_supplicant::kCaPath)
+ };
+
+ DBus::MessageIter writer;
+ for (size_t i = 0; i < arraysize(propertyvals); ++i) {
+ if (strlen(propertyvals[i].second) > 0) {
+ (*params)[propertyvals[i].first].writer().
+ append_string(propertyvals[i].second);
+ }
+ }
+}
+
} // namespace shill