shill: EapCredentials: Promote to a class
Promote the EapCredentials structure to a sovereign class with
a small set of getters and setters where necessary. Otherwise,
move most of the member manipulation (creating arguments for
wpa_supplicant and wimax_manager, Load() and Save()) interior
to the class. This involves a straightforwarnd but lengthy
refactor of just about everything that uses EapCredentials.
The EapCredentials object is ref-counted to allow it to be
shared between some services. For this reason, move the
"remote_certification" property out of EapCredentials into
Service since this property is strictly per-service.
BUG=chromium:227434
TEST=Unit tests, wired 802.1x and wifi EAP-TLS autotests
Change-Id: I167e71e1d9c934bc328a0e1d73f638e1ff50d238
Reviewed-on: https://gerrit.chromium.org/gerrit/47973
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Queue: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/Makefile b/Makefile
index 6a0d566..d79442f 100644
--- a/Makefile
+++ b/Makefile
@@ -223,6 +223,7 @@
dhcpcd_proxy.o \
diagnostics_reporter.o \
dns_client.o \
+ eap_credentials.o \
eap_listener.o \
endpoint.o \
ephemeral_profile.o \
@@ -343,6 +344,7 @@
dhcp_provider_unittest.o \
diagnostics_reporter_unittest.o \
dns_client_unittest.o \
+ eap_credentials_unittest.o \
eap_listener_unittest.o \
error_unittest.o \
ethernet_unittest.o \
@@ -380,6 +382,7 @@
mock_dhcp_proxy.o \
mock_diagnostics_reporter.o \
mock_dns_client.o \
+ mock_eap_credentials.o \
mock_eap_listener.o \
mock_ethernet.o \
mock_ethernet_service.o \
diff --git a/eap_credentials.cc b/eap_credentials.cc
new file mode 100644
index 0000000..11f3fad
--- /dev/null
+++ b/eap_credentials.cc
@@ -0,0 +1,479 @@
+// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/eap_credentials.h"
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <chromeos/dbus/service_constants.h>
+
+#include "shill/certificate_file.h"
+#include "shill/logging.h"
+#include "shill/key_value_store.h"
+#include "shill/metrics.h"
+#include "shill/nss.h"
+#include "shill/property_accessor.h"
+#include "shill/property_store.h"
+#include "shill/service.h"
+#include "shill/store_interface.h"
+#include "shill/wpa_supplicant.h"
+
+using base::FilePath;
+using std::map;
+using std::string;
+using std::vector;
+
+using std::string;
+
+namespace shill {
+
+const char EapCredentials::kStorageEapAnonymousIdentity[] =
+ "EAP.AnonymousIdentity";
+const char EapCredentials::kStorageEapCACert[] = "EAP.CACert";
+const char EapCredentials::kStorageEapCACertID[] = "EAP.CACertID";
+const char EapCredentials::kStorageEapCACertNSS[] = "EAP.CACertNSS";
+const char EapCredentials::kStorageEapCACertPEM[] = "EAP.CACertPEM";
+const char EapCredentials::kStorageEapCertID[] = "EAP.CertID";
+const char EapCredentials::kStorageEapClientCert[] = "EAP.ClientCert";
+const char EapCredentials::kStorageEapEap[] = "EAP.EAP";
+const char EapCredentials::kStorageEapIdentity[] = "EAP.Identity";
+const char EapCredentials::kStorageEapInnerEap[] = "EAP.InnerEAP";
+const char EapCredentials::kStorageEapKeyID[] = "EAP.KeyID";
+const char EapCredentials::kStorageEapKeyManagement[] = "EAP.KeyMgmt";
+const char EapCredentials::kStorageEapPIN[] = "EAP.PIN";
+const char EapCredentials::kStorageEapPassword[] = "EAP.Password";
+const char EapCredentials::kStorageEapPrivateKey[] = "EAP.PrivateKey";
+const char EapCredentials::kStorageEapPrivateKeyPassword[] =
+ "EAP.PrivateKeyPassword";
+const char EapCredentials::kStorageEapSubjectMatch[] =
+ "EAP.SubjectMatch";
+const char EapCredentials::kStorageEapUseSystemCAs[] = "EAP.UseSystemCAs";
+
+EapCredentials::EapCredentials() : use_system_cas_(true) {}
+
+EapCredentials::~EapCredentials() {}
+
+// static
+void EapCredentials::PopulateSupplicantProperties(
+ CertificateFile *certificate_file,
+ NSS *nss,
+ const vector<char> nss_identifier,
+ map<string, DBus::Variant> *params) const {
+ string ca_cert = ca_cert_;
+ if (!ca_cert_pem_.empty()) {
+ FilePath certfile =
+ certificate_file->CreateDERFromString(ca_cert_pem_);
+ if (certfile.empty()) {
+ LOG(ERROR) << "Unable to extract PEM certificate.";
+ } else {
+ ca_cert = certfile.value();
+ }
+ } else if (!ca_cert_nss_.empty()) {
+ FilePath certfile = nss->GetDERCertfile(ca_cert_nss_, nss_identifier);
+ if (certfile.empty()) {
+ LOG(ERROR) << "Unable to extract DER certificate: " << ca_cert_nss_;
+ } else {
+ ca_cert = certfile.value();
+ }
+ }
+
+
+ typedef std::pair<const char *, const char *> KeyVal;
+ KeyVal init_propertyvals[] = {
+ // Authentication properties.
+ KeyVal(WPASupplicant::kNetworkPropertyEapAnonymousIdentity,
+ anonymous_identity_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapCertId, cert_id_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapClientCert,
+ client_cert_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapIdentity, identity_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapKeyId, key_id_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapCaPassword,
+ password_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKey,
+ private_key_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKeyPassword,
+ private_key_password_.c_str()),
+
+ // Non-authentication properties.
+ KeyVal(WPASupplicant::kNetworkPropertyEapCaCert, ca_cert.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapCaCertId,
+ ca_cert_id_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapEap, eap_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapInnerEap,
+ inner_eap_.c_str()),
+ KeyVal(WPASupplicant::kNetworkPropertyEapSubjectMatch,
+ subject_match_.c_str())
+ };
+
+ vector<KeyVal> propertyvals(init_propertyvals,
+ init_propertyvals + arraysize(init_propertyvals));
+ if (use_system_cas_) {
+ propertyvals.push_back(KeyVal(
+ WPASupplicant::kNetworkPropertyCaPath, WPASupplicant::kCaPath));
+ } else if (ca_cert.empty()) {
+ LOG(WARNING) << __func__
+ << ": No certificate authorities are configured."
+ << " Server certificates will be accepted"
+ << " unconditionally.";
+ }
+
+ if (!cert_id_.empty() || !key_id_.empty() ||
+ !ca_cert_id_.empty()) {
+ propertyvals.push_back(KeyVal(
+ WPASupplicant::kNetworkPropertyEapPin, pin_.c_str()));
+ propertyvals.push_back(KeyVal(
+ WPASupplicant::kNetworkPropertyEngineId,
+ WPASupplicant::kEnginePKCS11));
+ // We can't use the propertyvals vector for this since this argument
+ // is a uint32, not a string.
+ (*params)[WPASupplicant::kNetworkPropertyEngine].writer().
+ append_uint32(WPASupplicant::kDefaultEngine);
+ }
+
+ vector<KeyVal>::iterator it;
+ for (it = propertyvals.begin(); it != propertyvals.end(); ++it) {
+ if (strlen((*it).second) > 0) {
+ (*params)[(*it).first].writer().append_string((*it).second);
+ }
+ }
+}
+
+// static
+void EapCredentials::PopulateWiMaxProperties(KeyValueStore *params) const {
+ if (!anonymous_identity_.empty()) {
+ params->SetString(wimax_manager::kEAPAnonymousIdentity,
+ anonymous_identity_);
+ }
+ if (!identity_.empty()) {
+ params->SetString(wimax_manager::kEAPUserIdentity, identity_);
+ }
+ if (!password_.empty()) {
+ params->SetString(wimax_manager::kEAPUserPassword, password_);
+ }
+}
+
+void EapCredentials::InitPropertyStore(PropertyStore *store) {
+ // Authentication properties.
+ store->RegisterString(flimflam::kEapAnonymousIdentityProperty,
+ &anonymous_identity_);
+ store->RegisterString(flimflam::kEAPCertIDProperty, &cert_id_);
+ store->RegisterString(flimflam::kEAPClientCertProperty, &client_cert_);
+ store->RegisterString(flimflam::kEapIdentityProperty, &identity_);
+ store->RegisterString(flimflam::kEAPKeyIDProperty, &key_id_);
+ HelpRegisterDerivedString(store,
+ flimflam::kEapKeyMgmtProperty,
+ &EapCredentials::GetKeyManagement,
+ &EapCredentials::SetKeyManagement);
+ HelpRegisterWriteOnlyDerivedString(store,
+ flimflam::kEapPasswordProperty,
+ &EapCredentials::SetEapPassword,
+ NULL,
+ &password_);
+ store->RegisterString(flimflam::kEAPPINProperty, &pin_);
+ store->RegisterString(flimflam::kEapPrivateKeyProperty, &private_key_);
+ HelpRegisterWriteOnlyDerivedString(store,
+ flimflam::kEapPrivateKeyPasswordProperty,
+ &EapCredentials::SetEapPrivateKeyPassword,
+ NULL,
+ &private_key_password_);
+
+ // Non-authentication properties.
+ store->RegisterString(kEapCaCertPemProperty, &ca_cert_pem_);
+ store->RegisterString(flimflam::kEapCaCertIDProperty, &ca_cert_id_);
+ store->RegisterString(flimflam::kEapCaCertNssProperty, &ca_cert_nss_);
+ store->RegisterString(flimflam::kEapCaCertProperty, &ca_cert_);
+ store->RegisterString(flimflam::kEAPEAPProperty, &eap_);
+ store->RegisterString(flimflam::kEapPhase2AuthProperty, &inner_eap_);
+ store->RegisterString(kEapSubjectMatchProperty, &subject_match_);
+ store->RegisterBool(flimflam::kEapUseSystemCAsProperty, &use_system_cas_);
+}
+
+// static
+bool EapCredentials::IsEapAuthenticationProperty(const string property) {
+ return
+ property == flimflam::kEapAnonymousIdentityProperty ||
+ property == flimflam::kEAPCertIDProperty ||
+ property == flimflam::kEAPClientCertProperty ||
+ property == flimflam::kEapIdentityProperty ||
+ property == flimflam::kEAPKeyIDProperty ||
+ property == flimflam::kEapKeyMgmtProperty ||
+ property == flimflam::kEapPasswordProperty ||
+ property == flimflam::kEAPPINProperty ||
+ property == flimflam::kEapPrivateKeyProperty ||
+ property == flimflam::kEapPrivateKeyPasswordProperty;
+}
+
+bool EapCredentials::IsConnectable() const {
+ // Identity is required.
+ if (identity_.empty()) {
+ SLOG(Service, 2) << "Not connectable: Identity is empty.";
+ return false;
+ }
+
+ if (!client_cert_.empty() || !cert_id_.empty()) {
+ // If a client certificate is being used, we must have a private key.
+ if (private_key_.empty() && key_id_.empty()) {
+ SLOG(Service, 2)
+ << "Not connectable: Client certificate but no private key.";
+ return false;
+ }
+ }
+ if (!cert_id_.empty() || !key_id_.empty() ||
+ !ca_cert_id_.empty()) {
+ // If PKCS#11 data is needed, a PIN is required.
+ if (pin_.empty()) {
+ SLOG(Service, 2) << "Not connectable: PKCS#11 data but no PIN.";
+ return false;
+ }
+ }
+
+ // For EAP-TLS, a client certificate is required.
+ if (eap_.empty() || eap_ == "TLS") {
+ if ((!client_cert_.empty() || !cert_id_.empty()) &&
+ (!private_key_.empty() || !key_id_.empty())) {
+ SLOG(Service, 2) << "Connectable: EAP-TLS with a client cert and key.";
+ return true;
+ }
+ }
+
+ // For EAP types other than TLS (e.g. EAP-TTLS or EAP-PEAP, password is the
+ // minimum requirement), at least an identity + password is required.
+ if (eap_.empty() || eap_ != "TLS") {
+ if (!password_.empty()) {
+ SLOG(Service, 2) << "Connectable. !EAP-TLS and has a password.";
+ return true;
+ }
+ }
+
+ SLOG(Service, 2)
+ << "Not connectable: No suitable EAP configuration was found.";
+ return false;
+}
+
+bool EapCredentials::IsConnectableUsingPassphrase() const {
+ return !identity_.empty() && !password_.empty();
+}
+
+void EapCredentials::Load(StoreInterface *storage, const string &id) {
+ // Authentication properties.
+ storage->GetCryptedString(id,
+ kStorageEapAnonymousIdentity,
+ &anonymous_identity_);
+ storage->GetString(id, kStorageEapCertID, &cert_id_);
+ storage->GetString(id, kStorageEapClientCert, &client_cert_);
+ storage->GetCryptedString(id, kStorageEapIdentity, &identity_);
+ storage->GetString(id, kStorageEapKeyID, &key_id_);
+ string key_management;
+ storage->GetString(id, kStorageEapKeyManagement, &key_management);
+ SetKeyManagement(key_management, NULL);
+ storage->GetCryptedString(id, kStorageEapPassword, &password_);
+ storage->GetString(id, kStorageEapPIN, &pin_);
+ storage->GetString(id, kStorageEapPrivateKey, &private_key_);
+ storage->GetCryptedString(id,
+ kStorageEapPrivateKeyPassword,
+ &private_key_password_);
+
+ // Non-authentication properties.
+ storage->GetString(id, kStorageEapCACert, &ca_cert_);
+ storage->GetString(id, kStorageEapCACertID, &ca_cert_id_);
+ storage->GetString(id, kStorageEapCACertNSS, &ca_cert_nss_);
+ storage->GetString(id, kStorageEapCACertPEM, &ca_cert_pem_);
+ storage->GetString(id, kStorageEapEap, &eap_);
+ storage->GetString(id, kStorageEapInnerEap, &inner_eap_);
+ storage->GetString(id, kStorageEapSubjectMatch, &subject_match_);
+ storage->GetBool(id, kStorageEapUseSystemCAs, &use_system_cas_);
+}
+
+void EapCredentials::OutputConnectionMetrics(
+ Metrics *metrics, Technology::Identifier technology) const {
+ Metrics::EapOuterProtocol outer_protocol =
+ Metrics::EapOuterProtocolStringToEnum(eap_);
+ metrics->SendEnumToUMA(
+ metrics->GetFullMetricName(Metrics::kMetricNetworkEapOuterProtocol,
+ technology),
+ outer_protocol,
+ Metrics::kMetricNetworkEapOuterProtocolMax);
+
+ Metrics::EapInnerProtocol inner_protocol =
+ Metrics::EapInnerProtocolStringToEnum(inner_eap_);
+ metrics->SendEnumToUMA(
+ metrics->GetFullMetricName(Metrics::kMetricNetworkEapInnerProtocol,
+ technology),
+ inner_protocol,
+ Metrics::kMetricNetworkEapInnerProtocolMax);
+}
+
+void EapCredentials::Save(StoreInterface *storage, const string &id,
+ bool save_credentials) const {
+ // Authentication properties.
+ Service::SaveString(storage,
+ id,
+ kStorageEapAnonymousIdentity,
+ anonymous_identity_,
+ true,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapCertID,
+ cert_id_,
+ false,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapClientCert,
+ client_cert_,
+ false,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapIdentity,
+ identity_,
+ true,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapKeyID,
+ key_id_,
+ false,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapKeyManagement,
+ key_management_,
+ false,
+ true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapPassword,
+ password_,
+ true,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapPIN,
+ pin_,
+ false,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapPrivateKey,
+ private_key_,
+ false,
+ save_credentials);
+ Service::SaveString(storage,
+ id,
+ kStorageEapPrivateKeyPassword,
+ private_key_password_,
+ true,
+ save_credentials);
+
+ // Non-authentication properties.
+ Service::SaveString(storage, id, kStorageEapCACert, ca_cert_, false, true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapCACertID,
+ ca_cert_id_,
+ false,
+ true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapCACertNSS,
+ ca_cert_nss_,
+ false,
+ true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapCACertPEM,
+ ca_cert_pem_,
+ false,
+ true);
+ Service::SaveString(storage, id, kStorageEapEap, eap_, false, true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapInnerEap,
+ inner_eap_,
+ false,
+ true);
+ Service::SaveString(storage,
+ id,
+ kStorageEapSubjectMatch,
+ subject_match_,
+ false,
+ true);
+ storage->SetBool(id, kStorageEapUseSystemCAs, use_system_cas_);
+}
+
+void EapCredentials::Reset() {
+ // Authentication properties.
+ anonymous_identity_ = "";
+ cert_id_ = "";
+ client_cert_ = "";
+ identity_ = "";
+ key_id_ = "";
+ key_management_ = "";
+ password_ = "";
+ pin_ = "";
+ private_key_ = "";
+ private_key_password_ = "";
+
+ // Non-authentication properties.
+ ca_cert_ = "";
+ ca_cert_id_ = "";
+ ca_cert_nss_ = "";
+ ca_cert_pem_ = "";
+ eap_ = "";
+ inner_eap_ = "";
+ subject_match_ = "";
+ use_system_cas_ = true;
+}
+
+void EapCredentials::SetEapPassword(const string &password, Error */*error*/) {
+ password_ = password;
+}
+
+void EapCredentials::SetEapPrivateKeyPassword(const string &password,
+ Error */*error*/) {
+ private_key_password_ = password;
+}
+
+string EapCredentials::GetKeyManagement(Error */*error*/) {
+ return key_management_;
+}
+
+void EapCredentials::SetKeyManagement(const std::string &key_management,
+ Error */*error*/) {
+ if (!key_management.empty()) {
+ key_management_ = key_management;
+ }
+}
+
+void EapCredentials::HelpRegisterDerivedString(
+ PropertyStore *store,
+ const string &name,
+ string(EapCredentials::*get)(Error *),
+ void(EapCredentials::*set)(const string&, Error *)) {
+ store->RegisterDerivedString(
+ name,
+ StringAccessor(new CustomAccessor<EapCredentials, string>(
+ this, get, set)));
+}
+
+void EapCredentials::HelpRegisterWriteOnlyDerivedString(
+ PropertyStore *store,
+ const string &name,
+ void(EapCredentials::*set)(const string &, Error *),
+ void(EapCredentials::*clear)(Error *),
+ const string *default_value) {
+ store->RegisterDerivedString(
+ name,
+ StringAccessor(
+ new CustomWriteOnlyAccessor<EapCredentials, string>(
+ this, set, clear, default_value)));
+}
+
+}
diff --git a/eap_credentials.h b/eap_credentials.h
index 63190b0..ef4dcc7 100644
--- a/eap_credentials.h
+++ b/eap_credentials.h
@@ -5,54 +5,197 @@
#ifndef SHILL_EAP_CREDENTIALS_H_
#define SHILL_EAP_CREDENTIALS_H_
+#include <map>
#include <string>
#include <vector>
+#include <base/file_path.h>
+#include <dbus-c++/dbus.h>
+
+#include "shill/technology.h"
+
namespace shill {
-struct EapCredentials {
- EapCredentials() : use_system_cas(true) {}
- // Who we identify ourselves as to the EAP authenticator.
- std::string identity;
- // The outer or only EAP authetnication type.
- std::string eap;
- // The inner EAP authentication type.
- std::string inner_eap;
+class CertificateFile;
+class Error;
+class KeyValueStore;
+class Metrics;
+class NSS;
+class PropertyStore;
+class StoreInterface;
+
+class EapCredentials {
+ public:
+ // TODO(pstew): Storage constants shouldn't need to be public
+ // crosbug.com/25813
+ static const char kStorageEapAnonymousIdentity[];
+ static const char kStorageEapCACert[];
+ static const char kStorageEapCACertID[];
+ static const char kStorageEapCACertNSS[];
+ static const char kStorageEapCACertPEM[];
+ static const char kStorageEapCertID[];
+ static const char kStorageEapClientCert[];
+ static const char kStorageEapEap[];
+ static const char kStorageEapIdentity[];
+ static const char kStorageEapInnerEap[];
+ static const char kStorageEapKeyID[];
+ static const char kStorageEapKeyManagement[];
+ static const char kStorageEapPIN[];
+ static const char kStorageEapPassword[];
+ static const char kStorageEapPrivateKey[];
+ static const char kStorageEapPrivateKeyPassword[];
+ static const char kStorageEapSubjectMatch[];
+ static const char kStorageEapUseSystemCAs[];
+
+ EapCredentials();
+ virtual ~EapCredentials();
+
+ // Add property accessors to the EAP credential parameters in |this| to
+ // |store|.
+ void InitPropertyStore(PropertyStore *store);
+
+ // Returns true if |property| is used for authentication in EapCredentials.
+ static bool IsEapAuthenticationProperty(const std::string property);
+
+ // Returns true if a connection can be made with |this| credentials using
+ // either passphrase or certificates.
+ virtual bool IsConnectable() const;
+
+ // Returns true if a connection can be made with |this| credentials using
+ // only passphrase properties.
+ virtual bool IsConnectableUsingPassphrase() const;
+
+ // Loads EAP properties from |storage| in group |id|.
+ virtual void Load(StoreInterface *store, const std::string &id);
+
+ // Output metrics about this EAP connection to |metrics| with technology
+ // |technology|.
+ virtual void OutputConnectionMetrics(Metrics *metrics,
+ Technology::Identifier technology) const;
+
+ // Populate the wpa_supplicant DBus parameter map |params| with the
+ // credentials in |this|. To do so, this function may use |certificate_file|
+ // or |nss| to export CA certificates to be passed to wpa_supplicant.
+ virtual void PopulateSupplicantProperties(
+ CertificateFile *certificate_file,
+ NSS *nss,
+ const std::vector<char> nss_identifier,
+ std::map<std::string, DBus::Variant> *params) const;
+
+ // Populate the WiMax connection parameters |params| with the
+ // credentials in |this|.
+ virtual void PopulateWiMaxProperties(
+ KeyValueStore *params) const;
+
+ // Save EAP properties to |storage| in group |id|. If |save_credentials|
+ // is true, passwords and identities that are a part of the credentials are
+ // also saved.
+ virtual void Save(StoreInterface *store, const std::string &id,
+ bool save_credentials) const;
+
+ // Restore EAP properties to their initial state.
+ virtual void Reset();
+
+ // Setter that guards against emptying the "Key Management" value.
+ virtual void SetKeyManagement(const std::string &key_management,
+ Error *error);
+
+ // Getters and setters.
+ virtual const std::string &identity() const { return identity_; }
+ void set_identity(const std::string &identity) {
+ identity_ = identity;
+ }
+ virtual const std::string &key_management() const { return key_management_; }
+ virtual void set_password(const std::string &password) {
+ password_ = password;
+ }
+
+ private:
+ friend class EapCredentialsTest;
+
+ // Expose a property in |store|, with the name |name|.
+ //
+ // Reads of the property will be handled by invoking |get|.
+ // Writes to the property will be handled by invoking |set|.
+ void HelpRegisterDerivedString(
+ PropertyStore *store,
+ const std::string &name,
+ std::string(EapCredentials::*get)(Error *error),
+ void(EapCredentials::*set)(const std::string &value, Error *error));
+
+ // Expose a property in |store|, with the name |name|.
+ //
+ // Reads of the property will be handled by invoking |get|.
+ //
+ // Clearing the property will be handled by invoking |clear|, or
+ // calling |set| with |default_value| (whichever is non-NULL). It
+ // is an error to call this method with both |clear| and
+ // |default_value| non-NULL.
+ void HelpRegisterWriteOnlyDerivedString(
+ PropertyStore *store,
+ const std::string &name,
+ void(EapCredentials::*set)(const std::string &value, Error *error),
+ void(EapCredentials::*clear)(Error *error),
+ const std::string *default_value);
+
+ // Assigns |value| to |key| in |storage| if |value| is non-empty and |save| is
+ // true. Otherwise, removes |key| from |storage|. If |crypted| is true, the
+ // value is encrypted.
+ static void SaveString(StoreInterface *storage,
+ const std::string &id,
+ const std::string &key,
+ const std::string &value,
+ bool crypted,
+ bool save);
+
+ // Setters for write-only RPC properties.
+ void SetEapPassword(const std::string &password, Error *error);
+ void SetEapPrivateKeyPassword(const std::string &password, Error *error);
+
+ // RPC getter for key_management_.
+ std::string GetKeyManagement(Error *error);
+
// When there is an inner EAP type, use this identity for the outer.
- std::string anonymous_identity;
- // Filename of the client certificate.
- std::string client_cert;
+ std::string anonymous_identity_;
// Locator for the client certificate within the security token.
- std::string cert_id;
- // Filename of the client private key.
- std::string private_key;
- // Password for decrypting the client private key file.
- std::string private_key_password;
+ std::string cert_id_;
+ // Filename of the client certificate.
+ std::string client_cert_;
+ // Who we identify ourselves as to the EAP authenticator.
+ std::string identity_;
// Locator for the client private key within the security token.
- std::string key_id;
- // Filename of the certificate authority (CA) certificate.
- std::string ca_cert;
- // Locator for the CA certificate within the security token.
- std::string ca_cert_id;
- // Locator for the CA certificate within the user NSS database.
- std::string ca_cert_nss;
- // Raw PEM contents of the CA certificate.
- std::string ca_cert_pem;
- // If true, use the system-wide CA database to authenticate the remote.
- bool use_system_cas;
- // PIN code for accessing the security token.
- std::string pin;
- // Password to use for EAP methods which require one.
- std::string password;
+ std::string key_id_;
// Key management algorithm to use after EAP succeeds.
- std::string key_management;
+ std::string key_management_;
+ // Password to use for EAP methods which require one.
+ std::string password_;
+ // PIN code for accessing the security token.
+ std::string pin_;
+ // Filename of the client private key.
+ std::string private_key_;
+ // Password for decrypting the client private key file.
+ std::string private_key_password_;
+
+ // Filename of the certificate authority (CA) certificate.
+ std::string ca_cert_;
+ // Locator for the CA certificate within the security token.
+ std::string ca_cert_id_;
+ // Locator for the CA certificate within the user NSS database.
+ std::string ca_cert_nss_;
+ // Raw PEM contents of the CA certificate.
+ std::string ca_cert_pem_;
+ // The outer or only EAP authetnication type.
+ std::string eap_;
+ // The inner EAP authentication type.
+ std::string inner_eap_;
// If non-empty, string to match remote subject against before connecting.
- std::string subject_match;
- // List of subject names reported by remote entity during TLS setup.
- std::vector<std::string> remote_certification;
+ std::string subject_match_;
+ // If true, use the system-wide CA database to authenticate the remote.
+ bool use_system_cas_;
+
+ DISALLOW_COPY_AND_ASSIGN(EapCredentials);
};
} // namespace shill
#endif // SHILL_EAP_CREDENTIALS_H_
-
diff --git a/eap_credentials_unittest.cc b/eap_credentials_unittest.cc
new file mode 100644
index 0000000..ed05e00
--- /dev/null
+++ b/eap_credentials_unittest.cc
@@ -0,0 +1,433 @@
+// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/eap_credentials.h"
+
+#include <base/stl_util.h>
+#include <chromeos/dbus/service_constants.h>
+#include <gtest/gtest.h>
+
+#include "shill/key_value_store.h"
+#include "shill/mock_certificate_file.h"
+#include "shill/mock_event_dispatcher.h"
+#include "shill/mock_log.h"
+#include "shill/mock_metrics.h"
+#include "shill/mock_nss.h"
+#include "shill/mock_property_store.h"
+#include "shill/mock_store.h"
+#include "shill/technology.h"
+#include "shill/wpa_supplicant.h"
+
+using base::FilePath;
+using std::map;
+using std::string;
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::DoAll;
+using testing::HasSubstr;
+using testing::Mock;
+using testing::Return;
+using testing::SetArgumentPointee;
+
+namespace shill {
+
+class EapCredentialsTest : public testing::Test {
+ public:
+ EapCredentialsTest() {}
+ virtual ~EapCredentialsTest() {}
+
+ protected:
+ void PopulateSupplicantProperties() {
+ eap_.PopulateSupplicantProperties(&certificate_file_, &nss_,
+ nss_identifier_, ¶ms_);
+ }
+
+ void SetAnonymousIdentity(const string &anonymous_identity) {
+ eap_.anonymous_identity_ = anonymous_identity;
+ }
+ void SetCACertNSS(const string &ca_cert_nss) {
+ eap_.ca_cert_nss_ = ca_cert_nss;
+ }
+ void SetCACertPEM(const string &ca_cert_pem) {
+ eap_.ca_cert_pem_ = ca_cert_pem;
+ }
+ void SetClientCert(const string &client_cert) {
+ eap_.client_cert_ = client_cert;
+ }
+ void SetCertId(const string &cert_id) {
+ eap_.cert_id_ = cert_id;
+ }
+ void SetEap(const string &eap) {
+ eap_.eap_ = eap;
+ }
+ void SetIdentity(const string &identity) {
+ eap_.identity_ = identity;
+ }
+ void SetInnerEap(const string &inner_eap) {
+ eap_.inner_eap_ = inner_eap;
+ }
+ void SetKeyId(const string &key_id) {
+ eap_.key_id_ = key_id;
+ }
+ const string &GetPassword() {
+ return eap_.password_;
+ }
+ void SetPassword(const string &password) {
+ eap_.password_ = password;
+ }
+ void SetPrivateKey(const string &private_key) {
+ eap_.private_key_ = private_key;
+ }
+ void SetPin(const string &pin) {
+ eap_.pin_ = pin;
+ }
+ void SetUseSystemCAs(bool use_system_cas) {
+ eap_.use_system_cas_ = use_system_cas;
+ }
+ bool IsReset() {
+ return
+ eap_.anonymous_identity_.empty() &&
+ eap_.cert_id_.empty() &&
+ eap_.client_cert_.empty() &&
+ eap_.identity_.empty() &&
+ eap_.key_id_.empty() &&
+ eap_.key_management_.empty() &&
+ eap_.password_.empty() &&
+ eap_.pin_.empty() &&
+ eap_.private_key_.empty() &&
+ eap_.private_key_password_.empty() &&
+ eap_.ca_cert_.empty() &&
+ eap_.ca_cert_id_.empty() &&
+ eap_.ca_cert_nss_.empty() &&
+ eap_.ca_cert_pem_.empty() &&
+ eap_.eap_.empty() &&
+ eap_.inner_eap_.empty() &&
+ eap_.subject_match_.empty() &&
+ eap_.use_system_cas_;
+ }
+
+ EapCredentials eap_;
+ MockCertificateFile certificate_file_;
+ MockNSS nss_;
+ vector<char> nss_identifier_;
+ map<string, ::DBus::Variant> params_;
+};
+
+TEST_F(EapCredentialsTest, PropertyStore) {
+ PropertyStore store;
+ eap_.InitPropertyStore(&store);
+ const string kIdentity("Cross-Eyed Mary");
+ Error error;
+ EXPECT_TRUE(store.SetStringProperty(flimflam::kEapIdentityProperty,
+ kIdentity, &error));
+ EXPECT_EQ(kIdentity, eap_.identity());
+}
+
+TEST_F(EapCredentialsTest, Connectable) {
+ // Empty EAP credentials should not make a 802.1x network connectable.
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // Identity alone is not enough.
+ SetIdentity("Steel Monkey");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // Set a password.
+ SetPassword("Angry Tapir");
+
+ // Empty "EAP" parameter is treated like "not EAP-TLS", and connectable.
+ EXPECT_TRUE(eap_.IsConnectable());
+
+ // Some other non-TLS EAP type.
+ SetEap("DodgeBall");
+ EXPECT_TRUE(eap_.IsConnectable());
+
+ // EAP-TLS requires certificate parameters, and cares not for passwords.
+ SetEap("TLS");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // Clearing the password won't help.
+ SetPassword("");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // A client cert by itself doesn't help.
+ SetClientCert("client-cert");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // A client cert and key will, however.
+ SetPrivateKey("client-cert");
+ EXPECT_TRUE(eap_.IsConnectable());
+
+ // A key-id (and cert) doesn't work.
+ SetKeyId("client-key-id");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // We need a PIN for the key id in addition.
+ SetPin("pin");
+ EXPECT_TRUE(eap_.IsConnectable());
+
+ // If we clear the "EAP" property, we just assume these valid certificate
+ // credentials are the ones to be used.
+ SetEap("");
+ EXPECT_TRUE(eap_.IsConnectable());
+
+ // Check that clearing the certificate parameter breaks us again.
+ SetClientCert("");
+ EXPECT_FALSE(eap_.IsConnectable());
+
+ // Setting the cert-id will fix things.
+ SetCertId("client-cert-id");
+ EXPECT_TRUE(eap_.IsConnectable());
+}
+
+TEST_F(EapCredentialsTest, ConnectableUsingPassphrase) {
+ EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
+
+ // No password.
+ SetIdentity("TestIdentity");
+ EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
+
+ // Success.
+ SetPassword("TestPassword");
+ EXPECT_TRUE(eap_.IsConnectableUsingPassphrase());
+
+ // Clear identity.
+ SetIdentity("");
+ EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
+}
+
+TEST_F(EapCredentialsTest, IsEapAuthenticationProperty) {
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapAnonymousIdentityProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEAPCertIDProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEAPClientCertProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapIdentityProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEAPKeyIDProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapKeyMgmtProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapPasswordProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEAPPINProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapPrivateKeyProperty));
+ EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapPrivateKeyPasswordProperty));
+
+ // It's easier to test that this function returns TRUE in every situation
+ // that it should, than to test all the cases it should return FALSE in.
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapCaCertProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapCaCertIDProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapCaCertNssProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ kEapCaCertPemProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEAPEAPProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapPhase2AuthProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ flimflam::kEapUseSystemCAsProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ kEapRemoteCertificationProperty));
+ EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
+ kEapSubjectMatchProperty));
+}
+
+TEST_F(EapCredentialsTest, LoadAndSave) {
+ MockStore store;
+ // For the values we're not testing...
+ EXPECT_CALL(store, GetCryptedString(_, _, _)).WillRepeatedly(Return(false));
+ EXPECT_CALL(store, GetString(_, _, _)).WillRepeatedly(Return(false));
+
+ const string kId("storage-id");
+ const string kIdentity("Purple Onion");
+ EXPECT_CALL(store, GetCryptedString(
+ kId, EapCredentials::kStorageEapIdentity, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(kIdentity), Return(true)));
+ const string kManagement("Shave and a Haircut");
+ EXPECT_CALL(store, GetString(
+ kId, EapCredentials::kStorageEapKeyManagement, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(kManagement), Return(true)));
+ const string kPassword("Two Bits");
+ EXPECT_CALL(store, GetCryptedString(
+ kId, EapCredentials::kStorageEapPassword, _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(kPassword), Return(true)));
+
+ eap_.Load(&store, kId);
+ Mock::VerifyAndClearExpectations(&store);
+
+ EXPECT_EQ(kIdentity, eap_.identity());
+ EXPECT_EQ(kManagement, eap_.key_management());
+ EXPECT_EQ(kPassword, GetPassword());
+
+ // Authentication properties are deleted from the store if they are empty,
+ // so we expect the fields that we haven't set to be deleted.
+ EXPECT_CALL(store, DeleteKey(_, _)).Times(AnyNumber());
+ EXPECT_CALL(store, SetCryptedString(_, _, _)).Times(0);
+ EXPECT_CALL(store, DeleteKey(kId, EapCredentials::kStorageEapIdentity));
+ EXPECT_CALL(store, SetString(
+ kId, EapCredentials::kStorageEapKeyManagement, kManagement));
+ EXPECT_CALL(store, DeleteKey(kId, EapCredentials::kStorageEapPassword));
+ eap_.Save(&store, kId, false);
+ Mock::VerifyAndClearExpectations(&store);
+
+ // Authentication properties are deleted from the store if they are empty,
+ // so we expect the fields that we haven't set to be deleted.
+ EXPECT_CALL(store, DeleteKey(_, _)).Times(AnyNumber());
+ EXPECT_CALL(store, SetCryptedString(
+ kId, EapCredentials::kStorageEapIdentity, kIdentity));
+ EXPECT_CALL(store, SetString(
+ kId, EapCredentials::kStorageEapKeyManagement, kManagement));
+ EXPECT_CALL(store, SetCryptedString(
+ kId, EapCredentials::kStorageEapPassword, kPassword));
+ eap_.Save(&store, kId, true);
+}
+
+TEST_F(EapCredentialsTest, OutputConnectionMetrics) {
+ Error unused_error;
+ SetEap(flimflam::kEapMethodPEAP);
+ SetInnerEap(flimflam::kEapPhase2AuthPEAPMSCHAPV2);
+
+ MockEventDispatcher dispatcher;
+ MockMetrics metrics(&dispatcher);
+ EXPECT_CALL(metrics, SendEnumToUMA("Network.Shill.Wifi.EapOuterProtocol",
+ Metrics::kEapOuterProtocolPeap,
+ Metrics::kEapOuterProtocolMax));
+ EXPECT_CALL(metrics, SendEnumToUMA("Network.Shill.Wifi.EapInnerProtocol",
+ Metrics::kEapInnerProtocolPeapMschapv2,
+ Metrics::kEapInnerProtocolMax));
+ eap_.OutputConnectionMetrics(&metrics, Technology::kWifi);
+}
+
+TEST_F(EapCredentialsTest, PopulateSupplicantProperties) {
+ SetIdentity("testidentity");
+ SetPin("xxxx");
+ PopulateSupplicantProperties();
+ // Test that only non-empty 802.1x properties are populated.
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapIdentity));
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapKeyId));
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
+
+ // Test that CA path is set by default.
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyCaPath));
+
+ // Test that hardware-backed security arguments are not set, since
+ // neither key-id nor cert-id were set.
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapPin));
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngine));
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngineId));
+}
+
+TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesNoSystemCAs) {
+ SetIdentity("testidentity");
+ SetUseSystemCAs(false);
+ PopulateSupplicantProperties();
+ // Test that CA path is not set if use_system_cas is explicitly false.
+ EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyCaPath));
+}
+
+TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesUsingHardwareAuth) {
+ SetIdentity("testidentity");
+ SetKeyId("key_id");
+ SetPin("xxxx");
+ PopulateSupplicantProperties();
+ // Test that EAP engine parameters set if key_id is set.
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapPin));
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapKeyId));
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngine));
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngineId));
+}
+
+TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesNSS) {
+ const string kNSSNickname("nss_nickname");
+ SetCACertNSS(kNSSNickname);
+ const string kNSSCertfile("/tmp/nss-cert");
+ FilePath nss_cert(kNSSCertfile);
+ nss_identifier_ = vector<char>(1, 'a');
+ EXPECT_CALL(nss_, GetDERCertfile(kNSSNickname, nss_identifier_))
+ .WillOnce(Return(nss_cert));
+ PopulateSupplicantProperties();
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
+ if (ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert)) {
+ EXPECT_EQ(kNSSCertfile, params_[WPASupplicant::kNetworkPropertyEapCaCert]
+ .reader().get_string());
+ }
+}
+
+TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesPEM) {
+ const string kPemCert("-pem-certificate-here-");
+ SetCACertPEM(kPemCert);
+ const string kPEMCertfile("/tmp/pem-cert");
+ FilePath pem_cert(kPEMCertfile);
+ EXPECT_CALL(certificate_file_, CreateDERFromString(kPemCert))
+ .WillOnce(Return(pem_cert));
+
+ PopulateSupplicantProperties();
+ EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
+ if (ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert)) {
+ EXPECT_EQ(kPEMCertfile, params_[WPASupplicant::kNetworkPropertyEapCaCert]
+ .reader().get_string());
+ }
+}
+
+TEST_F(EapCredentialsTest, PopulateWiMaxProperties) {
+ {
+ KeyValueStore parameters;
+ eap_.PopulateWiMaxProperties(¶meters);
+
+ EXPECT_FALSE(parameters.ContainsString(
+ wimax_manager::kEAPAnonymousIdentity));
+ EXPECT_FALSE(parameters.ContainsString(
+ wimax_manager::kEAPUserIdentity));
+ EXPECT_FALSE(parameters.ContainsString(
+ wimax_manager::kEAPUserPassword));
+ }
+
+ const string kAnonymousIdentity("TestAnonymousIdentity");
+ SetAnonymousIdentity(kAnonymousIdentity);
+ const string kIdentity("TestUserIdentity");
+ SetIdentity(kIdentity);
+ const string kPassword("TestPassword");
+ SetPassword(kPassword);
+
+ {
+ KeyValueStore parameters;
+ eap_.PopulateWiMaxProperties(¶meters);
+ EXPECT_EQ(kAnonymousIdentity, parameters.LookupString(
+ wimax_manager::kEAPAnonymousIdentity, ""));
+ EXPECT_EQ(kIdentity, parameters.LookupString(
+ wimax_manager::kEAPUserIdentity, ""));
+ EXPECT_EQ(kPassword, parameters.LookupString(
+ wimax_manager::kEAPUserPassword, ""));
+ }
+}
+
+TEST_F(EapCredentialsTest, Reset) {
+ EXPECT_TRUE(IsReset());
+ SetAnonymousIdentity("foo");
+ SetCACertNSS("foo");
+ SetCACertPEM("foo");
+ SetClientCert("foo");
+ SetCertId("foo");
+ SetEap("foo");
+ SetIdentity("foo");
+ SetInnerEap("foo");
+ SetKeyId("foo");
+ SetPassword("foo");
+ SetPrivateKey("foo");
+ SetPin("foo");
+ SetUseSystemCAs(false);
+ EXPECT_FALSE(IsReset());
+ eap_.Reset();
+ EXPECT_TRUE(IsReset());
+}
+
+} // namespace shill
diff --git a/ethernet.cc b/ethernet.cc
index 589b127..430c259 100644
--- a/ethernet.cc
+++ b/ethernet.cc
@@ -20,6 +20,7 @@
#include "shill/control_interface.h"
#include "shill/device.h"
#include "shill/device_info.h"
+#include "shill/eap_credentials.h"
#include "shill/eap_listener.h"
#include "shill/ethernet_service.h"
#include "shill/event_dispatcher.h"
@@ -260,8 +261,8 @@
bool Ethernet::StartEapAuthentication() {
map<string, DBus::Variant> params;
vector<char> nss_identifier(link_name().begin(), link_name().end());
- WPASupplicant::Populate8021xProperties(
- service_->eap(), &certificate_file_, nss_, nss_identifier, ¶ms);
+ service_->eap()->PopulateSupplicantProperties(
+ &certificate_file_, nss_, nss_identifier, ¶ms);
params[WPASupplicant::kNetworkPropertyEapKeyManagement].writer().
append_string(WPASupplicant::kKeyManagementIeee8021X);
params[WPASupplicant::kNetworkPropertyEapolFlags].writer().
diff --git a/ethernet_service.cc b/ethernet_service.cc
index 57e0bcf..1404375 100644
--- a/ethernet_service.cc
+++ b/ethernet_service.cc
@@ -17,6 +17,7 @@
#include "shill/control_interface.h"
#include "shill/device.h"
#include "shill/device_info.h"
+#include "shill/eap_credentials.h"
#include "shill/ethernet.h"
#include "shill/event_dispatcher.h"
#include "shill/manager.h"
@@ -41,6 +42,7 @@
set_auto_connect(true);
set_friendly_name("Ethernet");
SetStrength(kStrengthMax);
+ SetEapCredentials(new EapCredentials());
}
EthernetService::~EthernetService() { }
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index 8a4cfe2..9c10f95 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -11,6 +11,7 @@
#include <metrics/timer_mock.h>
#include "shill/mock_control.h"
+#include "shill/mock_eap_credentials.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_glib.h"
#include "shill/mock_manager.h"
@@ -49,13 +50,14 @@
ssid_,
flimflam::kModeManaged,
flimflam::kSecurityNone,
- false)) {
- }
+ false)),
+ eap_(new MockEapCredentials()) {}
virtual ~MetricsTest() {}
virtual void SetUp() {
metrics_.set_library(&library_);
+ wifi_service_->eap_.reset(eap_); // Passes ownership.
metrics_.collect_bootstats_ = false;
}
@@ -90,6 +92,7 @@
scoped_refptr<MockService> service_;
const std::vector<uint8_t> ssid_;
scoped_refptr<MockWiFiService> wifi_service_;
+ MockEapCredentials *eap_; // Owned by |wifi_service_|.
};
TEST_F(MetricsTest, TimeToConfig) {
@@ -205,20 +208,11 @@
Metrics::kWiFiNetworkPhyMode11a,
Metrics::kWiFiSecurity8021x,
-kStrength);
- EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.EapOuterProtocol",
- Metrics::kEapOuterProtocolPeap,
- Metrics::kEapOuterProtocolMax));
- EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.EapInnerProtocol",
- Metrics::kEapInnerProtocolPeapMschapv2,
- Metrics::kEapInnerProtocolMax));
wifi_service_->frequency_ = 2412;
wifi_service_->physical_mode_ = Metrics::kWiFiNetworkPhyMode11a;
wifi_service_->security_ = flimflam::kSecurity8021x;
wifi_service_->raw_signal_strength_ = kStrength;
- EapCredentials eap;
- eap.eap = flimflam::kEapMethodPEAP;
- eap.inner_eap = flimflam::kEapPhase2AuthPEAPMSCHAPV2;
- wifi_service_->set_eap(eap);
+ EXPECT_CALL(*eap_, OutputConnectionMetrics(&metrics_, Technology::kWifi));
metrics_.RegisterService(wifi_service_);
metrics_.NotifyServiceStateChanged(wifi_service_, Service::kStateConnected);
}
diff --git a/mock_eap_credentials.cc b/mock_eap_credentials.cc
new file mode 100644
index 0000000..456cdf8
--- /dev/null
+++ b/mock_eap_credentials.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/mock_eap_credentials.h"
+
+#include <gtest/gtest.h>
+
+namespace shill {
+
+MockEapCredentials::MockEapCredentials() : EapCredentials() {
+ ON_CALL(*this, key_management())
+ .WillByDefault(testing::ReturnRef(kDefaultKeyManagement));
+}
+
+MockEapCredentials::~MockEapCredentials() {}
+
+} // namespace shill
diff --git a/mock_eap_credentials.h b/mock_eap_credentials.h
new file mode 100644
index 0000000..3d14d68
--- /dev/null
+++ b/mock_eap_credentials.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_MOCK_EAP_CREDENTIALS_H_
+#define SHILL_MOCK_EAP_CREDENTIALS_H_
+
+#include "shill/eap_credentials.h"
+
+#include <gmock/gmock.h>
+
+namespace shill {
+
+class MockEapCredentials : public EapCredentials {
+ public:
+ MockEapCredentials();
+ virtual ~MockEapCredentials();
+
+ MOCK_CONST_METHOD0(IsConnectable, bool());
+ MOCK_CONST_METHOD0(IsConnectableUsingPassphrase, bool());
+ MOCK_METHOD2(Load, void(StoreInterface *store, const std::string &id));
+ MOCK_CONST_METHOD2(OutputConnectionMetrics,
+ void(Metrics *metrics, Technology::Identifier technology));
+ MOCK_CONST_METHOD4(PopulateSupplicantProperties, void(
+ CertificateFile *certificate_file,
+ NSS *nss,
+ const std::vector<char> nss_identifier,
+ std::map<std::string, DBus::Variant> *params));
+ MOCK_CONST_METHOD1(PopulateWiMaxProperties, void(KeyValueStore *params));
+ MOCK_CONST_METHOD3(Save, void(
+ StoreInterface *store, const std::string &id, bool save_credentials));
+ MOCK_METHOD0(Reset, void());
+ MOCK_METHOD2(SetKeyManagement, void(const std::string &key_management,
+ Error *error));
+ MOCK_CONST_METHOD0(identity, const std::string &());
+ MOCK_CONST_METHOD0(key_management, const std::string &());
+ MOCK_METHOD1(set_password, void(const std::string &password));
+
+ private:
+ std::string kDefaultKeyManagement;
+
+ DISALLOW_COPY_AND_ASSIGN(MockEapCredentials);
+};
+
+} // namespace shill
+
+#endif // SHILL_MOCK_EAP_CREDENTIALS_H_
diff --git a/profile_dbus_property_exporter.cc b/profile_dbus_property_exporter.cc
index 613a47b..a9881ef 100644
--- a/profile_dbus_property_exporter.cc
+++ b/profile_dbus_property_exporter.cc
@@ -11,6 +11,7 @@
#include <dbus-c++/dbus.h>
#include "shill/dbus_adaptor.h"
+#include "shill/eap_credentials.h"
#include "shill/error.h"
#include "shill/service.h"
#include "shill/store_interface.h"
@@ -66,11 +67,11 @@
bool ProfileDBusPropertyExporter::LoadEapServiceProperties(
PropertyList *properties,
Error */*error*/) {
- LoadString(properties, WiFiService::kStorageEapCACertID,
+ LoadString(properties, EapCredentials::kStorageEapCACertID,
flimflam::kEapCaCertIDProperty);
- LoadString(properties, WiFiService::kStorageEapCertID,
+ LoadString(properties, EapCredentials::kStorageEapCertID,
flimflam::kEAPCertIDProperty);
- LoadString(properties, WiFiService::kStorageEapKeyID,
+ LoadString(properties, EapCredentials::kStorageEapKeyID,
flimflam::kEAPKeyIDProperty);
return true;
}
diff --git a/profile_dbus_property_exporter_unittest.cc b/profile_dbus_property_exporter_unittest.cc
index 24cee52..2c1d6b3 100644
--- a/profile_dbus_property_exporter_unittest.cc
+++ b/profile_dbus_property_exporter_unittest.cc
@@ -10,6 +10,7 @@
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
+#include "shill/eap_credentials.h"
#include "shill/error.h"
#include "shill/mock_store.h"
#include "shill/service.h"
@@ -165,11 +166,11 @@
const string security("unbreakablecrypto");
ExpectStringProperty(WiFiService::kStorageSecurity, security);
const string ca_cert_id("ca-cert-id");
- ExpectStringProperty(WiFiService::kStorageEapCACertID, ca_cert_id);
+ ExpectStringProperty(EapCredentials::kStorageEapCACertID, ca_cert_id);
const string cert_id("cert-id");
- ExpectStringProperty(WiFiService::kStorageEapCertID, cert_id);
+ ExpectStringProperty(EapCredentials::kStorageEapCertID, cert_id);
const string key_id("key-id");
- ExpectStringProperty(WiFiService::kStorageEapKeyID, key_id);
+ ExpectStringProperty(EapCredentials::kStorageEapKeyID, key_id);
ProfileDBusPropertyExporter::PropertyList props;
diff --git a/service.cc b/service.cc
index 3508ad1..9d12995 100644
--- a/service.cc
+++ b/service.cc
@@ -19,6 +19,7 @@
#include "shill/connection.h"
#include "shill/control_interface.h"
#include "shill/diagnostics_reporter.h"
+#include "shill/eap_credentials.h"
#include "shill/error.h"
#include "shill/http_proxy.h"
#include "shill/logging.h"
@@ -72,23 +73,6 @@
const char Service::kStorageAutoConnect[] = "AutoConnect";
const char Service::kStorageCheckPortal[] = "CheckPortal";
-const char Service::kStorageEapAnonymousIdentity[] = "EAP.AnonymousIdentity";
-const char Service::kStorageEapCACert[] = "EAP.CACert";
-const char Service::kStorageEapCACertID[] = "EAP.CACertID";
-const char Service::kStorageEapCACertNSS[] = "EAP.CACertNSS";
-const char Service::kStorageEapCACertPEM[] = "EAP.CACertPEM";
-const char Service::kStorageEapCertID[] = "EAP.CertID";
-const char Service::kStorageEapClientCert[] = "EAP.ClientCert";
-const char Service::kStorageEapEap[] = "EAP.EAP";
-const char Service::kStorageEapIdentity[] = "EAP.Identity";
-const char Service::kStorageEapInnerEap[] = "EAP.InnerEAP";
-const char Service::kStorageEapKeyID[] = "EAP.KeyID";
-const char Service::kStorageEapKeyManagement[] = "EAP.KeyMgmt";
-const char Service::kStorageEapPIN[] = "EAP.PIN";
-const char Service::kStorageEapPassword[] = "EAP.Password";
-const char Service::kStorageEapPrivateKey[] = "EAP.PrivateKey";
-const char Service::kStorageEapPrivateKeyPassword[] = "EAP.PrivateKeyPassword";
-const char Service::kStorageEapUseSystemCAs[] = "EAP.UseSystemCAs";
const char Service::kStorageError[] = "Error";
const char Service::kStorageFavorite[] = "Favorite";
const char Service::kStorageGUID[] = "GUID";
@@ -172,37 +156,10 @@
HelpRegisterDerivedRpcIdentifier(flimflam::kDeviceProperty,
&Service::GetDeviceRpcId,
NULL);
+ store_.RegisterConstStrings(kEapRemoteCertificationProperty,
+ &remote_certification_);
store_.RegisterString(flimflam::kGuidProperty, &guid_);
- store_.RegisterString(flimflam::kEapIdentityProperty, &eap_.identity);
- store_.RegisterString(flimflam::kEAPEAPProperty, &eap_.eap);
- store_.RegisterString(flimflam::kEapPhase2AuthProperty, &eap_.inner_eap);
- store_.RegisterString(flimflam::kEapAnonymousIdentityProperty,
- &eap_.anonymous_identity);
- store_.RegisterString(flimflam::kEAPClientCertProperty, &eap_.client_cert);
- store_.RegisterString(flimflam::kEAPCertIDProperty, &eap_.cert_id);
- store_.RegisterString(flimflam::kEapPrivateKeyProperty, &eap_.private_key);
- HelpRegisterWriteOnlyDerivedString(flimflam::kEapPrivateKeyPasswordProperty,
- &Service::SetEAPPrivateKeyPassword,
- NULL,
- &eap_.private_key_password);
- store_.RegisterString(flimflam::kEAPKeyIDProperty, &eap_.key_id);
- store_.RegisterString(flimflam::kEapCaCertProperty, &eap_.ca_cert);
- store_.RegisterString(flimflam::kEapCaCertIDProperty, &eap_.ca_cert_id);
- store_.RegisterString(flimflam::kEapCaCertNssProperty, &eap_.ca_cert_nss);
- store_.RegisterString(kEapCaCertPemProperty, &eap_.ca_cert_pem);
- store_.RegisterString(flimflam::kEAPPINProperty, &eap_.pin);
- HelpRegisterWriteOnlyDerivedString(flimflam::kEapPasswordProperty,
- &Service::SetEAPPassword,
- NULL,
- &eap_.password);
- store_.RegisterString(flimflam::kEapKeyMgmtProperty, &eap_.key_management);
- store_.RegisterBool(flimflam::kEapUseSystemCAsProperty, &eap_.use_system_cas);
- store_.RegisterConstStrings(shill::kEapRemoteCertificationProperty,
- &eap_.remote_certification);
- store_.RegisterString(shill::kEapSubjectMatchProperty,
- &eap_.subject_match);
-
// TODO(ers): in flimflam clearing Error has the side-effect of
// setting the service state to IDLE. Is this important? I could
// see an autotest depending on it.
@@ -442,9 +399,14 @@
storage->GetString(id, kStorageProxyConfig, &proxy_config_);
storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
storage->GetString(id, kStorageUIData, &ui_data_);
- LoadEapCredentials(storage, id);
+
static_ip_parameters_.Load(storage, id);
+ if (mutable_eap()) {
+ mutable_eap()->Load(storage, id);
+ OnEapCredentialsChanged();
+ }
+
explicitly_disconnected_ = false;
favorite_ = true;
@@ -462,8 +424,11 @@
proxy_config_ = "";
save_credentials_ = true;
ui_data_ = "";
+ if (mutable_eap()) {
+ mutable_eap()->Reset();
+ }
+ ClearEAPCertification();
- UnloadEapCredentials();
Error error; // Ignored.
Disconnect(&error);
return false;
@@ -497,8 +462,10 @@
storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
SaveString(storage, id, kStorageUIData, ui_data_, false, true);
- SaveEapCredentials(storage, id);
static_ip_parameters_.Save(storage, id);
+ if (eap()) {
+ eap()->Save(storage, id, save_credentials_);
+ }
return true;
}
@@ -644,52 +611,7 @@
}
bool Service::Is8021xConnectable() const {
- // We mirror all the flimflam checks (see service.c:is_connectable()).
-
- // Identity is required.
- if (eap_.identity.empty()) {
- SLOG(Service, 2) << "Not connectable: Identity is empty.";
- return false;
- }
-
- if (!eap_.client_cert.empty() || !eap_.cert_id.empty()) {
- // If a client certificate is being used, we must have a private key.
- if (eap_.private_key.empty() && eap_.key_id.empty()) {
- SLOG(Service, 2)
- << "Not connectable. Client certificate but no private key.";
- return false;
- }
- }
- if (!eap_.cert_id.empty() || !eap_.key_id.empty() ||
- !eap_.ca_cert_id.empty()) {
- // If PKCS#11 data is needed, a PIN is required.
- if (eap_.pin.empty()) {
- SLOG(Service, 2) << "Not connectable. PKCS#11 data but no PIN.";
- return false;
- }
- }
-
- // For EAP-TLS, a client certificate is required.
- if (eap_.eap.empty() || eap_.eap == "TLS") {
- if ((!eap_.client_cert.empty() || !eap_.cert_id.empty()) &&
- (!eap_.private_key.empty() || !eap_.key_id.empty())) {
- SLOG(Service, 2) << "Connectable. EAP-TLS with a client cert and key.";
- return true;
- }
- }
-
- // For EAP types other than TLS (e.g. EAP-TTLS or EAP-PEAP, password is the
- // minimum requirement), at least an identity + password is required.
- if (eap_.eap.empty() || eap_.eap != "TLS") {
- if (!eap_.password.empty()) {
- SLOG(Service, 2) << "Connectable. !EAP-TLS and has a password.";
- return true;
- }
- }
-
- SLOG(Service, 2)
- << "Not connectable. No suitable EAP configuration was found.";
- return false;
+ return eap() && eap()->IsConnectable();
}
bool Service::AddEAPCertification(const string &name, size_t depth) {
@@ -701,13 +623,13 @@
return false;
}
- if (depth >= eap_.remote_certification.size()) {
- eap_.remote_certification.resize(depth + 1);
- } else if (name == eap_.remote_certification[depth]) {
+ if (depth >= remote_certification_.size()) {
+ remote_certification_.resize(depth + 1);
+ } else if (name == remote_certification_[depth]) {
return true;
}
- eap_.remote_certification[depth] = name;
+ remote_certification_[depth] = name;
LOG(INFO) << "Received certification for "
<< name
<< " at depth "
@@ -716,13 +638,15 @@
}
void Service::ClearEAPCertification() {
- eap_.remote_certification.clear();
+ remote_certification_.clear();
}
-void Service::set_eap(const EapCredentials &eap) {
- eap_ = eap;
- // Note: Connectability can only be updated by a subclass of Service
- // with knowledge of whether the service actually uses 802.1x credentials.
+void Service::SetEapCredentials(EapCredentials *eap) {
+ // This operation must be done at most once for the lifetime of the service.
+ CHECK(eap && !eap_);
+
+ eap_.reset(eap);
+ eap_->InitPropertyStore(mutable_store());
}
// static
@@ -996,18 +920,8 @@
}
void Service::OnPropertyChanged(const string &property) {
- if (Is8021x() &&
- (property == flimflam::kEAPCertIDProperty ||
- property == flimflam::kEAPClientCertProperty ||
- property == flimflam::kEAPKeyIDProperty ||
- property == flimflam::kEAPPINProperty ||
- property == flimflam::kEapCaCertIDProperty ||
- property == flimflam::kEapIdentityProperty ||
- property == flimflam::kEapKeyMgmtProperty ||
- property == flimflam::kEapPasswordProperty ||
- property == flimflam::kEapPrivateKeyProperty)) {
- // This notifies subclassess that EAP parameters have been changed.
- set_eap(eap_);
+ if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
+ OnEapCredentialsChanged();
}
SaveToProfile();
if ((property == flimflam::kCheckPortalProperty ||
@@ -1175,18 +1089,7 @@
StringsAccessor(new CustomAccessor<Service, Strings>(this, get, NULL)));
}
-void Service::HelpRegisterWriteOnlyDerivedString(
- const string &name,
- void(Service::*set)(const string &, Error *),
- void(Service::*clear)(Error *),
- const string *default_value) {
- store_.RegisterDerivedString(
- name,
- StringAccessor(
- new CustomWriteOnlyAccessor<Service, string>(
- this, set, clear, default_value)));
-}
-
+// static
void Service::SaveString(StoreInterface *storage,
const string &id,
const string &key,
@@ -1204,95 +1107,18 @@
storage->SetString(id, key, value);
}
-void Service::LoadEapCredentials(StoreInterface *storage, const string &id) {
- EapCredentials eap;
- storage->GetCryptedString(id, kStorageEapIdentity, &eap.identity);
- storage->GetString(id, kStorageEapEap, &eap.eap);
- storage->GetString(id, kStorageEapInnerEap, &eap.inner_eap);
- storage->GetCryptedString(id,
- kStorageEapAnonymousIdentity,
- &eap.anonymous_identity);
- storage->GetString(id, kStorageEapClientCert, &eap.client_cert);
- storage->GetString(id, kStorageEapCertID, &eap.cert_id);
- storage->GetString(id, kStorageEapPrivateKey, &eap.private_key);
- storage->GetCryptedString(id,
- kStorageEapPrivateKeyPassword,
- &eap.private_key_password);
- storage->GetString(id, kStorageEapKeyID, &eap.key_id);
- storage->GetString(id, kStorageEapCACert, &eap.ca_cert);
- storage->GetString(id, kStorageEapCACertID, &eap.ca_cert_id);
- storage->GetString(id, kStorageEapCACertNSS, &eap.ca_cert_nss);
- storage->GetString(id, kStorageEapCACertPEM, &eap.ca_cert_pem);
- storage->GetBool(id, kStorageEapUseSystemCAs, &eap.use_system_cas);
- storage->GetString(id, kStorageEapPIN, &eap.pin);
- storage->GetCryptedString(id, kStorageEapPassword, &eap.password);
- storage->GetString(id, kStorageEapKeyManagement, &eap.key_management);
- set_eap(eap);
-}
-
-void Service::SaveEapCredentials(StoreInterface *storage, const string &id) {
- bool save = save_credentials_;
- SaveString(storage, id, kStorageEapIdentity, eap_.identity, true, save);
- SaveString(storage, id, kStorageEapEap, eap_.eap, false, true);
- SaveString(storage, id, kStorageEapInnerEap, eap_.inner_eap, false, true);
- SaveString(storage,
- id,
- kStorageEapAnonymousIdentity,
- eap_.anonymous_identity,
- true,
- save);
- SaveString(storage, id, kStorageEapClientCert, eap_.client_cert, false, save);
- SaveString(storage, id, kStorageEapCertID, eap_.cert_id, false, save);
- SaveString(storage, id, kStorageEapPrivateKey, eap_.private_key, false, save);
- SaveString(storage,
- id,
- kStorageEapPrivateKeyPassword,
- eap_.private_key_password,
- true,
- save);
- SaveString(storage, id, kStorageEapKeyID, eap_.key_id, false, save);
- SaveString(storage, id, kStorageEapCACert, eap_.ca_cert, false, true);
- SaveString(storage, id, kStorageEapCACertID, eap_.ca_cert_id, false, true);
- SaveString(storage, id, kStorageEapCACertNSS, eap_.ca_cert_nss, false, true);
- SaveString(storage, id, kStorageEapCACertPEM, eap_.ca_cert_pem, false, true);
- storage->SetBool(id, kStorageEapUseSystemCAs, eap_.use_system_cas);
- SaveString(storage, id, kStorageEapPIN, eap_.pin, false, save);
- SaveString(storage, id, kStorageEapPassword, eap_.password, true, save);
- SaveString(storage,
- id,
- kStorageEapKeyManagement,
- eap_.key_management,
- false,
- true);
-}
-
-void Service::UnloadEapCredentials() {
- eap_.identity = "";
- eap_.eap = "";
- eap_.inner_eap = "";
- eap_.anonymous_identity = "";
- eap_.client_cert = "";
- eap_.cert_id = "";
- eap_.private_key = "";
- eap_.private_key_password = "";
- eap_.key_id = "";
- eap_.ca_cert = "";
- eap_.ca_cert_id = "";
- eap_.use_system_cas = true;
- eap_.pin = "";
- eap_.password = "";
-}
-
void Service::IgnoreParameterForConfigure(const string ¶meter) {
parameters_ignored_for_configure_.insert(parameter);
}
const string &Service::GetEAPKeyManagement() const {
- return eap_.key_management;
+ CHECK(eap());
+ return eap()->key_management();
}
void Service::SetEAPKeyManagement(const string &key_management) {
- eap_.key_management = key_management;
+ CHECK(mutable_eap());
+ mutable_eap()->SetKeyManagement(key_management, NULL);
}
bool Service::GetAutoConnect(Error */*error*/) {
@@ -1329,15 +1155,6 @@
check_portal_ = check_portal;
}
-void Service::SetEAPPassword(const string &password, Error */*error*/) {
- eap_.password = password;
-}
-
-void Service::SetEAPPrivateKeyPassword(const string &password,
- Error */*error*/) {
- eap_.private_key_password = password;
-}
-
void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
bool endpoint_auth) {
crypto_algorithm_ = crypto_algorithm;
diff --git a/service.h b/service.h
index 48b47ea..9ab30cb 100644
--- a/service.h
+++ b/service.h
@@ -22,7 +22,6 @@
#include "shill/adaptor_interfaces.h"
#include "shill/accessor_interface.h"
#include "shill/callbacks.h"
-#include "shill/eap_credentials.h"
#include "shill/property_store.h"
#include "shill/refptr_types.h"
#include "shill/shill_time.h"
@@ -37,6 +36,7 @@
class ControlInterface;
class DiagnosticsReporter;
+class EapCredentials;
class Endpoint;
class Error;
class EventDispatcher;
@@ -66,23 +66,6 @@
// crosbug.com/25813
static const char kStorageAutoConnect[];
static const char kStorageCheckPortal[];
- static const char kStorageEapAnonymousIdentity[];
- static const char kStorageEapCACert[];
- static const char kStorageEapCACertID[];
- static const char kStorageEapCACertNSS[];
- static const char kStorageEapCACertPEM[];
- static const char kStorageEapCertID[];
- static const char kStorageEapClientCert[];
- static const char kStorageEapEap[];
- static const char kStorageEapIdentity[];
- static const char kStorageEapInnerEap[];
- static const char kStorageEapKeyID[];
- static const char kStorageEapKeyManagement[];
- static const char kStorageEapPIN[];
- static const char kStorageEapPassword[];
- static const char kStorageEapPrivateKey[];
- static const char kStorageEapPrivateKeyPassword[];
- static const char kStorageEapUseSystemCAs[];
static const char kStorageError[];
static const char kStorageFavorite[];
static const char kStorageGUID[];
@@ -354,8 +337,8 @@
virtual Technology::Identifier technology() const { return technology_; }
std::string GetTechnologyString() const;
- const EapCredentials &eap() const { return eap_; }
- virtual void set_eap(const EapCredentials &eap);
+ const EapCredentials *eap() const { return eap_.get(); }
+ void SetEapCredentials(EapCredentials *eap);
bool save_credentials() const { return save_credentials_; }
void set_save_credentials(bool save) { save_credentials_ = save; }
@@ -407,9 +390,16 @@
// the RPC adaptor.
virtual void OnPropertyChanged(const std::string &property);
+ // Notification that occurs when an EAP credential property has been
+ // changed. Some service subclasses can choose to respond to this
+ // event.
+ virtual void OnEapCredentialsChanged() {}
+
// Called by the manager once after a resume.
virtual void OnAfterResume();
+ EapCredentials *mutable_eap() { return eap_.get(); }
+
PropertyStore *mutable_store() { return &store_; }
const PropertyStore &store() const { return store_; }
StaticIPParameters *mutable_static_ip_parameters() {
@@ -419,6 +409,16 @@
return static_ip_parameters_;
}
+ // Assigns |value| to |key| in |storage| if |value| is non-empty and |save| is
+ // true. Otherwise, removes |key| from |storage|. If |crypted| is true, the
+ // value is encrypted.
+ static void SaveString(StoreInterface *storage,
+ const std::string &id,
+ const std::string &key,
+ const std::string &value,
+ bool crypted,
+ bool save);
+
protected:
friend class base::RefCounted<Service>;
@@ -484,18 +484,6 @@
ServiceAdaptorInterface *adaptor() const { return adaptor_.get(); }
- // Assigns |value| to |key| in |storage| if |value| is non-empty and |save| is
- // true. Otherwise, removes |key| from |storage|. If |crypted| is true, the
- // value is encrypted.
- void SaveString(StoreInterface *storage,
- const std::string &id,
- const std::string &key,
- const std::string &value,
- bool crypted,
- bool save);
-
- void LoadEapCredentials(StoreInterface *storage, const std::string &id);
- void SaveEapCredentials(StoreInterface *storage, const std::string &id);
void UnloadEapCredentials();
// Ignore |parameter| when performing a Configure() operation.
@@ -512,8 +500,6 @@
EventDispatcher *dispatcher() const { return dispatcher_; }
const std::string &GetEAPKeyManagement() const;
virtual void SetEAPKeyManagement(const std::string &key_management);
- void SetEAPPassword(const std::string &password, Error *error);
- void SetEAPPrivateKeyPassword(const std::string &password, Error *error);
Manager *manager() const { return manager_; }
Metrics *metrics() const { return metrics_; }
@@ -548,8 +534,8 @@
FRIEND_TEST(ServiceTest, CalculateState);
FRIEND_TEST(ServiceTest, CalculateTechnology);
FRIEND_TEST(ServiceTest, Certification);
+ FRIEND_TEST(ServiceTest, ConfigureEapStringProperty);
FRIEND_TEST(ServiceTest, ConfigureIgnoredProperty);
- FRIEND_TEST(ServiceTest, ConfigureStringProperty);
FRIEND_TEST(ServiceTest, Constructor);
FRIEND_TEST(ServiceTest, GetIPConfigRpcIdentifier);
FRIEND_TEST(ServiceTest, GetProperties);
@@ -682,7 +668,7 @@
std::string ui_data_;
std::string guid_;
bool save_credentials_;
- EapCredentials eap_; // Only saved if |save_credentials_| is true.
+ scoped_ptr<EapCredentials> eap_;
Technology::Identifier technology_;
// The time of the most recent failure. Value is 0 if the service is
// not currently failed.
@@ -710,6 +696,9 @@
// to PII concerns.
std::string friendly_name_;
+ // List of subject names reported by remote entity during TLS setup.
+ std::vector<std::string> remote_certification_;
+
scoped_ptr<ServiceAdaptorInterface> adaptor_;
scoped_ptr<HTTPProxy> http_proxy_;
ConnectionRefPtr connection_;
diff --git a/service_unittest.cc b/service_unittest.cc
index d16397a..eab8380 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -23,6 +23,7 @@
#include "shill/mock_connection.h"
#include "shill/mock_device_info.h"
#include "shill/mock_diagnostics_reporter.h"
+#include "shill/mock_eap_credentials.h"
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_log.h"
#include "shill/mock_manager.h"
@@ -70,10 +71,12 @@
metrics(),
&mock_manager_)),
storage_id_(ServiceUnderTest::kStorageId),
- power_manager_(new MockPowerManager(NULL, &proxy_factory_)) {
+ power_manager_(new MockPowerManager(NULL, &proxy_factory_)),
+ eap_(new MockEapCredentials()) {
service_->time_ = &time_;
DefaultValue<Timestamp>::Set(Timestamp());
service_->diagnostics_reporter_ = &diagnostics_reporter_;
+ service_->eap_.reset(eap_); // Passes ownership.
mock_manager_.running_ = true;
mock_manager_.set_power_manager(power_manager_); // Passes ownership.
}
@@ -182,6 +185,7 @@
string storage_id_;
TestProxyFactory proxy_factory_;
MockPowerManager *power_manager_; // Owned by |mock_manager_|.
+ MockEapCredentials *eap_; // Owned by |service_|.
};
class AllMockServiceTest : public testing::Test {
@@ -295,6 +299,22 @@
{
::DBus::Error error;
EXPECT_TRUE(DBusAdaptor::SetProperty(service_->mutable_store(),
+ flimflam::kGuidProperty,
+ PropertyStoreTest::kStringV,
+ &error));
+ }
+ // Ensure that EAP properties cannot be set on services with no EAP
+ // credentials. Use service2_ here since we're have some code in
+ // ServiceTest::SetUp() that fiddles with service_->eap_.
+ {
+ ::DBus::Error error;
+ EXPECT_FALSE(DBusAdaptor::SetProperty(service2_->mutable_store(),
+ flimflam::kEAPEAPProperty,
+ PropertyStoreTest::kStringV,
+ &error));
+ EXPECT_EQ(invalid_prop(), error.name());
+ service2_->SetEapCredentials(new EapCredentials());
+ EXPECT_TRUE(DBusAdaptor::SetProperty(service2_->mutable_store(),
flimflam::kEAPEAPProperty,
PropertyStoreTest::kStringV,
&error));
@@ -354,6 +374,7 @@
EXPECT_CALL(storage, GetBool(storage_id_, _, _)).Times(AnyNumber());
EXPECT_CALL(storage,
GetBool(storage_id_, Service::kStorageSaveCredentials, _));
+ EXPECT_CALL(*eap_, Load(&storage, storage_id_));
EXPECT_TRUE(service_->Load(&storage));
}
@@ -410,6 +431,7 @@
SetBool(storage_id_,
Service::kStorageSaveCredentials,
service_->save_credentials()));
+ EXPECT_CALL(*eap_, Save(&storage, storage_id_, true));
EXPECT_TRUE(service_->Save(&storage));
}
@@ -426,6 +448,7 @@
EXPECT_FALSE(service_->explicitly_disconnected_);
service_->explicitly_disconnected_ = true;
EXPECT_FALSE(service_->has_ever_connected_);
+ EXPECT_CALL(*eap_, Load(&storage, storage_id_));
ASSERT_TRUE(service_->Load(&storage));
// TODO(pstew): Only two string properties in the service are tested as
// a sentinel that properties are being set and reset at the right times.
@@ -438,6 +461,7 @@
EXPECT_FALSE(service_->explicitly_disconnected_);
EXPECT_TRUE(service_->has_ever_connected_);
service_->explicitly_disconnected_ = true;
+ EXPECT_CALL(*eap_, Reset());
service_->Unload();
EXPECT_EQ(string(""), service_->ui_data_);
EXPECT_EQ(string(""), service_->guid_);
@@ -589,6 +613,7 @@
// again.
NiceMock<MockStore> storage;
EXPECT_CALL(storage, ContainsGroup(storage_id_)).WillOnce(Return(true));
+ EXPECT_CALL(*eap_, Load(&storage, storage_id_));
EXPECT_TRUE(service_->Load(&storage));
EXPECT_TRUE(service_->IsAutoConnectable(&reason));
@@ -741,16 +766,35 @@
}
TEST_F(ServiceTest, ConfigureStringProperty) {
- const string kEAPManagement0 = "management_zero";
- const string kEAPManagement1 = "management_one";
- service_->SetEAPKeyManagement(kEAPManagement0);
- ASSERT_EQ(kEAPManagement0, service_->GetEAPKeyManagement());
+ const string kGuid0 = "guid_zero";
+ const string kGuid1 = "guid_one";
+ service_->set_guid(kGuid0);
+ ASSERT_EQ(kGuid0, service_->guid());
KeyValueStore args;
- args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
+ args.SetString(flimflam::kGuidProperty, kGuid1);
Error error;
service_->Configure(args, &error);
EXPECT_TRUE(error.IsSuccess());
- EXPECT_EQ(kEAPManagement1, service_->GetEAPKeyManagement());
+ EXPECT_EQ(kGuid1, service_->guid());
+}
+
+TEST_F(ServiceTest, ConfigureEapStringProperty) {
+ MockEapCredentials *eap = new MockEapCredentials();
+ service2_->SetEapCredentials(eap); // Passes ownership.
+
+ const string kEAPManagement0 = "management_zero";
+ const string kEAPManagement1 = "management_one";
+ service2_->SetEAPKeyManagement(kEAPManagement0);
+
+ EXPECT_CALL(*eap, key_management())
+ .WillOnce(ReturnRef(kEAPManagement0));
+ ASSERT_EQ(kEAPManagement0, service2_->GetEAPKeyManagement());
+ KeyValueStore args;
+ EXPECT_CALL(*eap, SetKeyManagement(kEAPManagement1, _));
+ args.SetString(flimflam::kEapKeyMgmtProperty, kEAPManagement1);
+ Error error;
+ service2_->Configure(args, &error);
+ EXPECT_TRUE(error.IsSuccess());
}
TEST_F(ServiceTest, ConfigureIntProperty) {
@@ -998,13 +1042,13 @@
EXPECT_TRUE(service_->connectable());
}
-// Make sure a property is registered as a write only property
-// by reading and comparing all string properties returned on the store.
-// Subtle: We need to convert the test argument back and forth between
-// string and ::DBus::Variant because this is the parameter type that
-// our supeclass (PropertyStoreTest) is declared with.
-class ReadOnlyServicePropertyTest : public ServiceTest {};
-TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
+class WriteOnlyServicePropertyTest : public ServiceTest {};
+TEST_P(WriteOnlyServicePropertyTest, PropertyWriteOnly) {
+ // Use a real EapCredentials instance since the base Service class
+ // contains no write-only properties.
+ EapCredentials eap;
+ eap.InitPropertyStore(service_->mutable_store());
+
string property(GetParam().reader().get_string());
Error error;
EXPECT_FALSE(service_->store().GetStringProperty(property, NULL, &error));
@@ -1012,8 +1056,8 @@
}
INSTANTIATE_TEST_CASE_P(
- ReadOnlyServicePropertyTestInstance,
- ReadOnlyServicePropertyTest,
+ WriteOnlyServicePropertyTestInstance,
+ WriteOnlyServicePropertyTest,
Values(
DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
@@ -1058,15 +1102,15 @@
mock_device_info.reset();
}
-class ServiceWithMockSetEap : public ServiceUnderTest {
+class ServiceWithMockOnEapCredentialsChanged : public ServiceUnderTest {
public:
- ServiceWithMockSetEap(ControlInterface *control_interface,
- EventDispatcher *dispatcher,
- Metrics *metrics,
- Manager *manager)
+ ServiceWithMockOnEapCredentialsChanged(ControlInterface *control_interface,
+ EventDispatcher *dispatcher,
+ Metrics *metrics,
+ Manager *manager)
: ServiceUnderTest(control_interface, dispatcher, metrics, manager),
is_8021x_(false) {}
- MOCK_METHOD1(set_eap, void(const EapCredentials &eap));
+ MOCK_METHOD0(OnEapCredentialsChanged, void());
virtual bool Is8021x() const { return is_8021x_; }
void set_is_8021x(bool is_8021x) { is_8021x_ = is_8021x; }
@@ -1075,32 +1119,32 @@
};
TEST_F(ServiceTest, SetEAPCredentialsOverRPC) {
- scoped_refptr<ServiceWithMockSetEap> service(
- new ServiceWithMockSetEap(control_interface(),
- dispatcher(),
- metrics(),
- &mock_manager_));
+ scoped_refptr<ServiceWithMockOnEapCredentialsChanged> service(
+ new ServiceWithMockOnEapCredentialsChanged(control_interface(),
+ dispatcher(),
+ metrics(),
+ &mock_manager_));
string eap_credential_properties[] = {
+ flimflam::kEapAnonymousIdentityProperty,
flimflam::kEAPCertIDProperty,
flimflam::kEAPClientCertProperty,
- flimflam::kEAPKeyIDProperty,
- flimflam::kEAPPINProperty,
- flimflam::kEapCaCertIDProperty,
flimflam::kEapIdentityProperty,
+ flimflam::kEAPKeyIDProperty,
flimflam::kEapPasswordProperty,
- flimflam::kEapPrivateKeyProperty
+ flimflam::kEAPPINProperty,
+ flimflam::kEapPrivateKeyProperty,
+ flimflam::kEapPrivateKeyPasswordProperty
};
string eap_non_credential_properties[] = {
+ flimflam::kEapCaCertIDProperty,
+ flimflam::kEapCaCertNssProperty,
flimflam::kEAPEAPProperty,
flimflam::kEapPhase2AuthProperty,
- flimflam::kEapAnonymousIdentityProperty,
- flimflam::kEapPrivateKeyPasswordProperty,
- flimflam::kEapCaCertNssProperty,
flimflam::kEapUseSystemCAsProperty
};
// While this is not an 802.1x-based service, none of these property
// changes should cause a call to set_eap().
- EXPECT_CALL(*service, set_eap(_)).Times(0);
+ EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(0);
for (size_t i = 0; i < arraysize(eap_credential_properties); ++i)
service->OnPropertyChanged(eap_credential_properties[i]);
for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
@@ -1112,7 +1156,7 @@
// When this is an 802.1x-based service, set_eap should be called for
// all credential-carrying properties.
for (size_t i = 0; i < arraysize(eap_credential_properties); ++i) {
- EXPECT_CALL(*service, set_eap(_)).Times(1);
+ EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(1);
service->OnPropertyChanged(eap_credential_properties[i]);
Mock::VerifyAndClearExpectations(service.get());
}
@@ -1120,17 +1164,17 @@
// The key management property is a special case. While not strictly
// a credential, it can change which credentials are used. Therefore it
// should also trigger a call to set_eap();
- EXPECT_CALL(*service, set_eap(_)).Times(1);
+ EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(1);
service->OnPropertyChanged(flimflam::kEapKeyMgmtProperty);
Mock::VerifyAndClearExpectations(service.get());
- EXPECT_CALL(*service, set_eap(_)).Times(0);
+ EXPECT_CALL(*service, OnEapCredentialsChanged()).Times(0);
for (size_t i = 0; i < arraysize(eap_non_credential_properties); ++i)
service->OnPropertyChanged(eap_non_credential_properties[i]);
}
TEST_F(ServiceTest, Certification) {
- EXPECT_FALSE(service_->eap_.remote_certification.size());
+ EXPECT_FALSE(service_->remote_certification_.size());
ScopedMockLog log;
EXPECT_CALL(log, Log(logging::LOG_WARNING, _,
@@ -1140,7 +1184,7 @@
kSubject, Service::kEAPMaxCertificationElements));
EXPECT_FALSE(service_->AddEAPCertification(
kSubject, Service::kEAPMaxCertificationElements + 1));
- EXPECT_FALSE(service_->eap_.remote_certification.size());
+ EXPECT_FALSE(service_->remote_certification_.size());
Mock::VerifyAndClearExpectations(&log);
EXPECT_CALL(log,
@@ -1150,11 +1194,11 @@
kSubject, Service::kEAPMaxCertificationElements - 1));
Mock::VerifyAndClearExpectations(&log);
EXPECT_EQ(Service::kEAPMaxCertificationElements,
- service_->eap_.remote_certification.size());
+ service_->remote_certification_.size());
for (size_t i = 0; i < Service::kEAPMaxCertificationElements - 1; ++i) {
- EXPECT_TRUE(service_->eap_.remote_certification[i].empty());
+ EXPECT_TRUE(service_->remote_certification_[i].empty());
}
- EXPECT_EQ(kSubject, service_->eap_.remote_certification[
+ EXPECT_EQ(kSubject, service_->remote_certification_[
Service::kEAPMaxCertificationElements - 1]);
// Re-adding the same name in the same position should not generate a log.
@@ -1168,6 +1212,9 @@
.Times(1);
EXPECT_TRUE(service_->AddEAPCertification(
kSubject + "x", Service::kEAPMaxCertificationElements - 1));
+
+ service_->ClearEAPCertification();
+ EXPECT_TRUE(service_->remote_certification_.empty());
}
TEST_F(ServiceTest, NoteDisconnectEventIdle) {
diff --git a/wifi_service.cc b/wifi_service.cc
index 3e5ed3f..22196a4 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -19,6 +19,7 @@
#include "shill/certificate_file.h"
#include "shill/control_interface.h"
#include "shill/device.h"
+#include "shill/eap_credentials.h"
#include "shill/error.h"
#include "shill/event_dispatcher.h"
#include "shill/ieee80211.h"
@@ -105,6 +106,8 @@
}
set_friendly_name(ssid_string);
+ SetEapCredentials(new EapCredentials());
+
// TODO(quiche): determine if it is okay to set EAP.KeyManagement for
// a service that is not 802.1x.
if (Is8021x()) {
@@ -366,21 +369,7 @@
Metrics::kMetricNetworkSecurityMax);
if (Is8021x()) {
- Metrics::EapOuterProtocol outer_protocol =
- Metrics::EapOuterProtocolStringToEnum(eap().eap);
- metrics()->SendEnumToUMA(
- metrics()->GetFullMetricName(Metrics::kMetricNetworkEapOuterProtocol,
- technology()),
- outer_protocol,
- Metrics::kMetricNetworkEapOuterProtocolMax);
-
- Metrics::EapInnerProtocol inner_protocol =
- Metrics::EapInnerProtocolStringToEnum(eap().inner_eap);
- metrics()->SendEnumToUMA(
- metrics()->GetFullMetricName(Metrics::kMetricNetworkEapInnerProtocol,
- technology()),
- inner_protocol,
- Metrics::kMetricNetworkEapInnerProtocolMax);
+ eap()->OutputConnectionMetrics(metrics(), technology());
}
// We invert the sign of the signal strength value, since UMA histograms
@@ -492,8 +481,8 @@
if (GetEAPKeyManagement().empty())
SetEAPKeyManagement("WPA-EAP");
vector<char> nss_identifier(ssid_.begin(), ssid_.end());
- WPASupplicant::Populate8021xProperties(
- eap(), certificate_file_.get(), nss_, nss_identifier, ¶ms);
+ eap()->PopulateSupplicantProperties(
+ certificate_file_.get(), nss_, nss_identifier, ¶ms);
ClearEAPCertification();
} else if (security_ == flimflam::kSecurityPsk ||
security_ == flimflam::kSecurityRsn ||
@@ -988,14 +977,7 @@
}
}
-void WiFiService::set_eap(const EapCredentials &new_eap) {
- EapCredentials modified_eap = new_eap;
-
- // An empty key_management field is invalid. Prevent it, if possible.
- if (modified_eap.key_management.empty()) {
- modified_eap.key_management = eap().key_management;
- }
- Service::set_eap(modified_eap);
+void WiFiService::OnEapCredentialsChanged() {
ClearCachedCredentials();
UpdateConnectable();
}
diff --git a/wifi_service.h b/wifi_service.h
index 9f62608..bf30b13 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -114,7 +114,7 @@
// Override from parent Service class to correctly update connectability
// when the EAP credentials change for 802.1x networks.
- void set_eap(const EapCredentials &eap);
+ void OnEapCredentialsChanged();
// Override from parent Service class to register hidden services once they
// have been configured.
diff --git a/wifi_service_unittest.cc b/wifi_service_unittest.cc
index 1d02151..bd89b81 100644
--- a/wifi_service_unittest.cc
+++ b/wifi_service_unittest.cc
@@ -22,6 +22,7 @@
#include "shill/mock_adaptors.h"
#include "shill/mock_certificate_file.h"
#include "shill/mock_control.h"
+#include "shill/mock_eap_credentials.h"
#include "shill/mock_log.h"
#include "shill/mock_nss.h"
#include "shill/mock_profile.h"
@@ -47,6 +48,7 @@
using ::testing::Mock;
using ::testing::NiceMock;
using ::testing::Return;
+using ::testing::ReturnRef;
using ::testing::SetArgumentPointee;
using ::testing::StrEq;
using ::testing::StrNe;
@@ -72,15 +74,27 @@
protected:
static const char fake_mac[];
+ MockEapCredentials *SetMockEap(
+ const WiFiServiceRefPtr &service) {
+ MockEapCredentials *eap = new MockEapCredentials();
+ service->eap_.reset(eap); // Passes ownership.
+ return eap;
+ }
bool CheckConnectable(const std::string &security, const char *passphrase,
- EapCredentials *eap) {
+ bool is_1x_connectable) {
Error error;
WiFiServiceRefPtr service = MakeSimpleService(security);
if (passphrase)
service->SetPassphrase(passphrase, &error);
- if (eap) {
- service->set_eap(*eap);
+ MockEapCredentials *eap = SetMockEap(service);
+ EXPECT_CALL(*eap, IsConnectable())
+ .WillRepeatedly(Return(is_1x_connectable));
+ const string kKeyManagement8021x(WPASupplicant::kKeyManagementIeee8021X);
+ if (security == flimflam::kSecurityWep && is_1x_connectable) {
+ EXPECT_CALL(*eap, key_management())
+ .WillRepeatedly(ReturnRef(kKeyManagement8021x));
}
+ service->OnEapCredentialsChanged();
return service->connectable();
}
WiFiEndpoint *MakeEndpoint(const string &ssid, const string &bssid,
@@ -468,14 +482,25 @@
TEST_F(WiFiServiceTest, ConnectTask8021x) {
WiFiServiceRefPtr service = MakeServiceWithWiFi(flimflam::kSecurity8021x);
- EapCredentials eap;
- eap.identity = "identity";
- eap.password = "mumble";
- service->set_eap(eap);
+ service->mutable_eap()->set_identity("identity");
+ service->mutable_eap()->set_password("mumble");
+ service->OnEapCredentialsChanged();
EXPECT_CALL(*wifi(), ConnectTo(service.get(), EAPSecurityArgs()));
service->Connect(NULL, "in test");
}
+TEST_F(WiFiServiceTest, ConnectTask8021xWithMockEap) {
+ WiFiServiceRefPtr service = MakeServiceWithWiFi(flimflam::kSecurity8021x);
+ MockEapCredentials *eap = SetMockEap(service);
+ EXPECT_CALL(*eap, IsConnectable()).WillOnce(Return(true));
+ service->OnEapCredentialsChanged();
+ EXPECT_CALL(*eap, PopulateSupplicantProperties(_, _, _, _));
+ // The mocked function does not actually set EAP parameters so we cannot
+ // expect them to be set.
+ EXPECT_CALL(*wifi(), ConnectTo(service.get(), _));
+ service->Connect(NULL, "in test");
+}
+
TEST_F(WiFiServiceTest, ConnectTaskAdHocFrequency) {
vector<uint8_t> ssid(1, 'a');
WiFiEndpointRefPtr endpoint_nofreq =
@@ -619,11 +644,10 @@
TEST_F(WiFiServiceTest, ConnectTaskDynamicWEP) {
WiFiServiceRefPtr wifi_service = MakeServiceWithWiFi(flimflam::kSecurityWep);
- EapCredentials eap;
- eap.key_management = "IEEE8021X";
- eap.identity = "something";
- eap.password = "mumble";
- wifi_service->set_eap(eap);
+ wifi_service->mutable_eap()->SetKeyManagement("IEEE8021X", NULL);
+ wifi_service->mutable_eap()->set_identity("something");
+ wifi_service->mutable_eap()->set_password("mumble");
+ wifi_service->OnEapCredentialsChanged();
EXPECT_CALL(*wifi(),
ConnectTo(wifi_service.get(), DynamicWEPArgs()));
wifi_service->Connect(NULL, "in test");
@@ -684,7 +708,7 @@
// Any change to EAP parameters (including a null one) will trigger cache
// removal. This is a lot less granular than the passphrase checks above.
EXPECT_CALL(*wifi(), ClearCachedCredentials(wifi_service.get()));
- wifi_service->set_eap(EapCredentials());
+ wifi_service->OnEapCredentialsChanged();
Mock::VerifyAndClearExpectations(wifi());
}
}
@@ -1068,52 +1092,33 @@
TEST_F(WiFiServiceTest, Connectable) {
// Open network should be connectable.
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurityNone, NULL, NULL));
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurityNone, NULL, false));
// Open network should remain connectable if we try to set a password on it.
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurityNone, "abcde", NULL));
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurityNone, "abcde", false));
// WEP network with passphrase set should be connectable.
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWep, "abcde", NULL));
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWep, "abcde", false));
// WEP network without passphrase set should NOT be connectable.
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWep, NULL, NULL));
+ EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWep, NULL, false));
// A bad passphrase should not make a WEP network connectable.
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWep, "a", NULL));
+ EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWep, "a", false));
// Similar to WEP, for WPA.
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWpa, "abcdefgh", NULL));
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWpa, NULL, NULL));
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWpa, "a", NULL));
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWpa, "abcdefgh", false));
+ EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWpa, NULL, false));
+ EXPECT_FALSE(CheckConnectable(flimflam::kSecurityWpa, "a", false));
- // Unconfigured 802.1x should NOT be connectable.
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, NULL));
+ // 802.1x without connectable EAP credentials should NOT be connectable.
+ EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, false));
- EapCredentials eap;
- // Empty EAP credentials should not make a 802.1x network connectable.
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
+ // 802.1x with connectable EAP credentials should be connectable.
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurity8021x, NULL, true));
- eap.identity = "something";
- // If client certificate is being used, a private key must exist.
- eap.client_cert = "some client cert";
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
- eap.private_key = "some private key";
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
-
- // Identity is always required.
- eap.identity.clear();
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
-
- eap.identity = "something";
- // For non EAP-TLS types, a password is required.
- eap.eap = "Non-TLS";
- EXPECT_FALSE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
- eap.password = "some password";
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurity8021x, NULL, &eap));
// Dynamic WEP + 802.1X should be connectable under the same conditions.
- eap.key_management = "IEEE8021X";
- EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWep, NULL, &eap));
+ EXPECT_TRUE(CheckConnectable(flimflam::kSecurityWep, NULL, true));
}
TEST_F(WiFiServiceTest, IsAutoConnectable) {
diff --git a/wimax_provider_unittest.cc b/wimax_provider_unittest.cc
index 93997eb..01c768b 100644
--- a/wimax_provider_unittest.cc
+++ b/wimax_provider_unittest.cc
@@ -10,6 +10,7 @@
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
+#include "shill/eap_credentials.h"
#include "shill/glib.h"
#include "shill/key_file_store.h"
#include "shill/mock_dbus_manager.h"
@@ -515,12 +516,12 @@
// GetService should create a service with only identifying parameters set.
EXPECT_EQ(kName, GetServiceFriendlyName(service));
- EXPECT_EQ("", service->eap().identity);
+ EXPECT_EQ("", service->eap()->identity());
// After configuring the service, other parameters should be set.
service->Configure(args, &e);
EXPECT_TRUE(e.IsSuccess());
- EXPECT_EQ(kIdentity, service->eap().identity);
+ EXPECT_EQ(kIdentity, service->eap()->identity());
}
TEST_F(WiMaxProviderTest, SelectCarrier) {
diff --git a/wimax_service.cc b/wimax_service.cc
index f59c336..4b75461 100644
--- a/wimax_service.cc
+++ b/wimax_service.cc
@@ -11,6 +11,7 @@
#include <base/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
+#include "shill/eap_credentials.h"
#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/manager.h"
@@ -40,6 +41,8 @@
store->RegisterBool(flimflam::kPassphraseRequiredProperty, &need_passphrase_);
store->RegisterConstString(kNetworkIdProperty, &network_id_);
+ SetEapCredentials(new EapCredentials());
+
IgnoreParameterForConfigure(kNetworkIdProperty);
// Initialize a default storage identifier based on the service's unique
@@ -52,16 +55,7 @@
void WiMaxService::GetConnectParameters(KeyValueStore *parameters) const {
CHECK(parameters);
- if (!eap().anonymous_identity.empty()) {
- parameters->SetString(wimax_manager::kEAPAnonymousIdentity,
- eap().anonymous_identity);
- }
- if (!eap().identity.empty()) {
- parameters->SetString(wimax_manager::kEAPUserIdentity, eap().identity);
- }
- if (!eap().password.empty()) {
- parameters->SetString(wimax_manager::kEAPUserPassword, eap().password);
- }
+ eap()->PopulateWiMaxProperties(parameters);
}
RpcIdentifier WiMaxService::GetNetworkObjectPath() const {
@@ -204,9 +198,8 @@
return true;
}
-void WiMaxService::set_eap(const EapCredentials &eap) {
- Service::set_eap(eap);
- need_passphrase_ = eap.identity.empty() || eap.password.empty();
+void WiMaxService::OnEapCredentialsChanged() {
+ need_passphrase_ = !eap()->IsConnectableUsingPassphrase();
UpdateConnectable();
}
@@ -226,6 +219,7 @@
}
const string id = GetStorageIdentifier();
storage->SetString(id, kStorageNetworkId, network_id_);
+
return true;
}
@@ -267,10 +261,8 @@
}
void WiMaxService::ClearPassphrase() {
- EapCredentials creds = eap();
- creds.password.clear();
- // Updates the service credentials and connectability status.
- set_eap(creds);
+ mutable_eap()->set_password("");
+ OnEapCredentialsChanged();
}
} // namespace shill
diff --git a/wimax_service.h b/wimax_service.h
index 7bf6612..a63314d 100644
--- a/wimax_service.h
+++ b/wimax_service.h
@@ -70,7 +70,7 @@
virtual void Disconnect(Error *error);
virtual std::string GetStorageIdentifier() const;
virtual bool Is8021x() const;
- virtual void set_eap(const EapCredentials &eap);
+ virtual void OnEapCredentialsChanged();
virtual bool Save(StoreInterface *storage);
virtual bool Unload();
virtual void SetState(ConnectState state);
@@ -80,7 +80,7 @@
FRIEND_TEST(WiMaxServiceTest, GetDeviceRpcId);
FRIEND_TEST(WiMaxServiceTest, IsAutoConnectable);
FRIEND_TEST(WiMaxServiceTest, OnSignalStrengthChanged);
- FRIEND_TEST(WiMaxServiceTest, SetEAP);
+ FRIEND_TEST(WiMaxServiceTest, Connectable);
FRIEND_TEST(WiMaxServiceTest, SetState);
FRIEND_TEST(WiMaxServiceTest, StartStop);
diff --git a/wimax_service_unittest.cc b/wimax_service_unittest.cc
index 81e2c8b..76ce419 100644
--- a/wimax_service_unittest.cc
+++ b/wimax_service_unittest.cc
@@ -11,6 +11,7 @@
#include "shill/error.h"
#include "shill/nice_mock_control.h"
#include "shill/mock_adaptors.h"
+#include "shill/mock_eap_credentials.h"
#include "shill/mock_manager.h"
#include "shill/mock_metrics.h"
#include "shill/mock_store.h"
@@ -20,6 +21,7 @@
using std::string;
using testing::_;
+using testing::Mock;
using testing::NiceMock;
using testing::Return;
using wimax_manager::kEAPAnonymousIdentity;
@@ -48,10 +50,12 @@
device_(new MockWiMax(&control_, NULL, &metrics_, &manager_,
kTestLinkName, kTestAddress, kTestInterfaceIndex,
kTestPath)),
- service_(new WiMaxService(&control_, NULL, &metrics_, &manager_)) {
+ service_(new WiMaxService(&control_, NULL, &metrics_, &manager_)),
+ eap_(new MockEapCredentials()) {
service_->set_friendly_name(kTestName);
service_->set_network_id(kTestNetworkId);
service_->InitStorageIdentifier();
+ service_->eap_.reset(eap_); // Passes ownership.
}
virtual ~WiMaxServiceTest() {}
@@ -76,32 +80,13 @@
NiceMock<MockMetrics> metrics_;
scoped_refptr<MockWiMax> device_;
WiMaxServiceRefPtr service_;
+ MockEapCredentials *eap_; // Owned by |service_|.
};
TEST_F(WiMaxServiceTest, GetConnectParameters) {
- {
- KeyValueStore parameters;
- service_->GetConnectParameters(¶meters);
-
- EXPECT_FALSE(parameters.ContainsString(kEAPAnonymousIdentity));
- EXPECT_FALSE(parameters.ContainsString(kEAPUserIdentity));
- EXPECT_FALSE(parameters.ContainsString(kEAPUserPassword));
- }
- {
- EapCredentials eap;
- eap.anonymous_identity = "TestAnonymousIdentity";
- eap.identity = "TestUserIdentity";
- eap.password = "TestPassword";
- service_->set_eap(eap);
-
- KeyValueStore parameters;
- service_->GetConnectParameters(¶meters);
-
- EXPECT_EQ(eap.anonymous_identity,
- parameters.LookupString(kEAPAnonymousIdentity, ""));
- EXPECT_EQ(eap.identity, parameters.LookupString(kEAPUserIdentity, ""));
- EXPECT_EQ(eap.password, parameters.LookupString(kEAPUserPassword, ""));
- }
+ KeyValueStore parameters;
+ EXPECT_CALL(*eap_, PopulateWiMaxProperties(¶meters));
+ service_->GetConnectParameters(¶meters);
}
TEST_F(WiMaxServiceTest, GetDeviceRpcId) {
@@ -152,38 +137,41 @@
EXPECT_FALSE(service_->proxy_.get());
}
-TEST_F(WiMaxServiceTest, SetEAP) {
- ServiceRefPtr base_service = service_;
- EXPECT_TRUE(base_service->Is8021x());
+TEST_F(WiMaxServiceTest, Connectable) {
+ EXPECT_TRUE(service_->Is8021x());
EXPECT_TRUE(service_->need_passphrase_);
- EXPECT_FALSE(base_service->connectable());
+ EXPECT_FALSE(service_->connectable());
- // No password.
- EapCredentials eap;
- eap.identity = "TestIdentity";
- base_service->set_eap(eap);
+ EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
+ .WillOnce(Return(false))
+ .WillRepeatedly(Return(true));
+
+ // No WiMaxCredentials.
+ service_->OnEapCredentialsChanged();
EXPECT_TRUE(service_->need_passphrase_);
- EXPECT_FALSE(base_service->connectable());
+ EXPECT_FALSE(service_->connectable());
- // Not started.
- eap.password = "TestPassword";
- base_service->set_eap(eap);
+ // Not started (no proxy).
+ service_->OnEapCredentialsChanged();
EXPECT_FALSE(service_->need_passphrase_);
- EXPECT_FALSE(base_service->connectable());
+ EXPECT_FALSE(service_->connectable());
// Connectable.
service_->proxy_.reset(proxy_.release());
ExpectUpdateService();
- base_service->set_eap(eap);
+ service_->OnEapCredentialsChanged();
EXPECT_FALSE(service_->need_passphrase_);
- EXPECT_TRUE(base_service->connectable());
+ EXPECT_TRUE(service_->connectable());
- // Reset password.
+ // Reset WimaxConnectable state.
+ Mock::VerifyAndClearExpectations(eap_);
+ EXPECT_CALL(*eap_, set_password(""));
+ EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
+ .WillRepeatedly(Return(false));
ExpectUpdateService();
service_->ClearPassphrase();
EXPECT_TRUE(service_->need_passphrase_);
- EXPECT_FALSE(base_service->connectable());
- EXPECT_TRUE(base_service->eap().password.empty());
+ EXPECT_FALSE(service_->connectable());
}
TEST_F(WiMaxServiceTest, ConvertIdentifierToNetworkId) {
@@ -258,31 +246,33 @@
EXPECT_CALL(manager_, wimax_provider())
.Times(2)
.WillRepeatedly(Return(&provider));
- EapCredentials eap;
- eap.identity = "TestUserIdentity";
- service_->set_eap(eap);
+ EXPECT_CALL(*eap_, Reset());
+ EXPECT_CALL(*eap_, set_password(""));
+ EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
+ .WillRepeatedly(Return(false));
EXPECT_CALL(provider, OnServiceUnloaded(_)).WillOnce(Return(false));
EXPECT_FALSE(service_->Unload());
- EXPECT_TRUE(service_->eap().identity.empty());
- eap.identity = "TestUserIdentity";
- service_->set_eap(eap);
+ Mock::VerifyAndClearExpectations(eap_);
+
+ EXPECT_CALL(*eap_, Reset());
+ EXPECT_CALL(*eap_, set_password(""));
+ EXPECT_CALL(*eap_, IsConnectableUsingPassphrase())
+ .WillRepeatedly(Return(false));
EXPECT_CALL(provider, OnServiceUnloaded(_)).WillOnce(Return(true));
EXPECT_TRUE(service_->Unload());
- EXPECT_TRUE(service_->eap().identity.empty());
}
TEST_F(WiMaxServiceTest, SetState) {
service_->device_ = device_;
- ServiceRefPtr base_service = service_;
EXPECT_EQ(Service::kStateIdle, service_->state());
EXPECT_CALL(manager_, UpdateService(_));
- base_service->SetState(Service::kStateAssociating);
+ service_->SetState(Service::kStateAssociating);
EXPECT_EQ(Service::kStateAssociating, service_->state());
EXPECT_TRUE(service_->device_);
EXPECT_CALL(manager_, UpdateService(_));
- base_service->SetState(Service::kStateFailure);
+ service_->SetState(Service::kStateFailure);
EXPECT_EQ(Service::kStateFailure, service_->state());
EXPECT_FALSE(service_->device_);
}
diff --git a/wpa_supplicant.cc b/wpa_supplicant.cc
index 4f0edf2..3be81f1 100644
--- a/wpa_supplicant.cc
+++ b/wpa_supplicant.cc
@@ -144,88 +144,6 @@
SHIMDIR "/wpa_supplicant.conf";
// static
-void WPASupplicant::Populate8021xProperties(
- const EapCredentials &eap, CertificateFile *certificate_file,
- NSS *nss, const vector<char> nss_identifier,
- map<string, DBus::Variant> *params) {
- string ca_cert = eap.ca_cert;
- if (!eap.ca_cert_pem.empty()) {
- FilePath certfile =
- certificate_file->CreateDERFromString(eap.ca_cert_pem);
- if (certfile.empty()) {
- LOG(ERROR) << "Unable to extract PEM certificate.";
- } else {
- ca_cert = certfile.value();
- }
- } else if (!eap.ca_cert_nss.empty()) {
- FilePath certfile = nss->GetDERCertfile(eap.ca_cert_nss, nss_identifier);
- if (certfile.empty()) {
- LOG(ERROR) << "Unable to extract DER certificate: " << eap.ca_cert_nss;
- } else {
- ca_cert = certfile.value();
- }
- }
-
-
- typedef std::pair<const char *, const char *> KeyVal;
- KeyVal init_propertyvals[] = {
- KeyVal(WPASupplicant::kNetworkPropertyEapIdentity, eap.identity.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapEap, eap.eap.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapInnerEap,
- eap.inner_eap.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapAnonymousIdentity,
- eap.anonymous_identity.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapClientCert,
- eap.client_cert.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKey,
- eap.private_key.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKeyPassword,
- eap.private_key_password.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapCaCert, ca_cert.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapCaPassword,
- eap.password.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapCertId, eap.cert_id.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapKeyId, eap.key_id.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapCaCertId,
- eap.ca_cert_id.c_str()),
- KeyVal(WPASupplicant::kNetworkPropertyEapSubjectMatch,
- eap.subject_match.c_str())
- };
-
- vector<KeyVal> propertyvals(init_propertyvals,
- init_propertyvals + arraysize(init_propertyvals));
- if (eap.use_system_cas) {
- propertyvals.push_back(KeyVal(
- WPASupplicant::kNetworkPropertyCaPath, WPASupplicant::kCaPath));
- } else if (ca_cert.empty()) {
- LOG(WARNING) << __func__
- << ": No certificate authorities are configured."
- << " Server certificates will be accepted"
- << " unconditionally.";
- }
-
- if (!eap.cert_id.empty() || !eap.key_id.empty() ||
- !eap.ca_cert_id.empty()) {
- propertyvals.push_back(KeyVal(
- WPASupplicant::kNetworkPropertyEapPin, eap.pin.c_str()));
- propertyvals.push_back(KeyVal(
- WPASupplicant::kNetworkPropertyEngineId,
- WPASupplicant::kEnginePKCS11));
- // We can't use the propertyvals vector for this since this argument
- // is a uint32, not a string.
- (*params)[WPASupplicant::kNetworkPropertyEngine].writer().
- append_uint32(WPASupplicant::kDefaultEngine);
- }
-
- vector<KeyVal>::iterator it;
- for (it = propertyvals.begin(); it != propertyvals.end(); ++it) {
- if (strlen((*it).second) > 0) {
- (*params)[(*it).first].writer().append_string((*it).second);
- }
- }
-}
-
-// static
bool WPASupplicant::ExtractRemoteCertification(
const std::map<std::string, DBus::Variant> &properties,
std::string *subject, uint32 *depth) {
diff --git a/wpa_supplicant.h b/wpa_supplicant.h
index 78260e9..90728d0 100644
--- a/wpa_supplicant.h
+++ b/wpa_supplicant.h
@@ -14,10 +14,6 @@
namespace shill {
-class CertificateFile;
-struct EapCredentials;
-class NSS;
-
class WPASupplicant {
public:
static const char kBSSPropertyBSSID[];
@@ -137,14 +133,6 @@
static const char kSupplicantConfPath[];
- // Populate the wpa_supplicant DBus parameter map |params| with the
- // credentials in |eap|. To do so, this function may use |certificate_file|
- // or |nss| to export CA certificates to be passed to wpa_supplicant.
- static void Populate8021xProperties(
- const EapCredentials &eap, CertificateFile *certificate_file,
- NSS *nss, const std::vector<char> nss_identifier,
- std::map<std::string, DBus::Variant> *params);
-
// Retrieve the |subject| and |depth| of an a remote certifying entity,
// as contained the the |properties| to a Certification event from
// wpa_supplicant. Returns true if an |subject| and |depth| were
diff --git a/wpa_supplicant_unittest.cc b/wpa_supplicant_unittest.cc
index de8b681..d0b0cb5 100644
--- a/wpa_supplicant_unittest.cc
+++ b/wpa_supplicant_unittest.cc
@@ -4,23 +4,14 @@
#include "shill/wpa_supplicant.h"
-#include <base/file_path.h>
-#include <base/stl_util.h>
-#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include "shill/eap_credentials.h"
-#include "shill/mock_certificate_file.h"
#include "shill/mock_log.h"
-#include "shill/mock_nss.h"
-using base::FilePath;
using std::map;
using std::string;
-using std::vector;
using testing::_;
using testing::EndsWith;
-using testing::Return;
namespace shill {
@@ -30,95 +21,18 @@
virtual ~WPASupplicantTest() {}
protected:
- typedef std::map<std::string, DBus::Variant> PropertyMap;
+ typedef map<string, DBus::Variant> PropertyMap;
- void Populate() {
- WPASupplicant::Populate8021xProperties(eap_, &certificate_file_,
- &nss_, nss_identifier_, ¶ms_);
- }
-
- EapCredentials eap_;
- MockCertificateFile certificate_file_;
- MockNSS nss_;
- vector<char> nss_identifier_;
- map<string, ::DBus::Variant> params_;
+ PropertyMap property_map_;
};
-TEST_F(WPASupplicantTest, Populate8021x) {
- eap_.identity = "testidentity";
- eap_.pin = "xxxx";
- Populate();
- // Test that only non-empty 802.1x properties are populated.
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapIdentity));
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapKeyId));
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
-
- // Test that CA path is set by default.
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyCaPath));
-
- // Test that hardware-backed security arguments are not set.
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapPin));
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngine));
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngineId));
-}
-
-TEST_F(WPASupplicantTest, Populate8021xNoSystemCAs) {
- eap_.identity = "testidentity";
- eap_.use_system_cas = false;
- Populate();
- // Test that CA path is not set if use_system_cas is explicitly false.
- EXPECT_FALSE(ContainsKey(params_, WPASupplicant::kNetworkPropertyCaPath));
-}
-
-TEST_F(WPASupplicantTest, Populate8021xUsingHardwareAuth) {
- eap_.identity = "testidentity";
- eap_.key_id = "key_id";
- eap_.pin = "xxxx";
- Populate();
- // Test that EAP engine parameters set if key_id is set.
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapPin));
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapKeyId));
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngine));
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEngineId));
-}
-
-TEST_F(WPASupplicantTest, Populate8021xNSS) {
- eap_.ca_cert_nss = "nss_nickname";
- const string kNSSCertfile("/tmp/nss-cert");
- FilePath nss_cert(kNSSCertfile);
- nss_identifier_ = vector<char>(1, 'a');
- EXPECT_CALL(nss_, GetDERCertfile(eap_.ca_cert_nss, nss_identifier_))
- .WillOnce(Return(nss_cert));
- Populate();
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
- if (ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert)) {
- EXPECT_EQ(kNSSCertfile, params_[WPASupplicant::kNetworkPropertyEapCaCert]
- .reader().get_string());
- }
-}
-
-TEST_F(WPASupplicantTest, Populate8021xPEM) {
- eap_.ca_cert_pem = "-pem-certificate-here-";
- const string kPEMCertfile("/tmp/pem-cert");
- FilePath pem_cert(kPEMCertfile);
- EXPECT_CALL(certificate_file_, CreateDERFromString(eap_.ca_cert_pem))
- .WillOnce(Return(pem_cert));
-
- Populate();
- EXPECT_TRUE(ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert));
- if (ContainsKey(params_, WPASupplicant::kNetworkPropertyEapCaCert)) {
- EXPECT_EQ(kPEMCertfile, params_[WPASupplicant::kNetworkPropertyEapCaCert]
- .reader().get_string());
- }
-}
-
TEST_F(WPASupplicantTest, ExtractRemoteCertificationEmpty) {
string subject;
uint32 depth = 0;
ScopedMockLog log;
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no depth parameter.")));
EXPECT_FALSE(WPASupplicant::ExtractRemoteCertification(
- PropertyMap(), &subject, &depth));
+ property_map_, &subject, &depth));
EXPECT_EQ("", subject);
EXPECT_EQ(0, depth);
}
@@ -127,14 +41,13 @@
string subject;
const uint32 kDepthValue = 100;
uint32 depth = kDepthValue - 1;
- PropertyMap property_map;
- property_map[WPASupplicant::kInterfacePropertyDepth]
+ property_map_[WPASupplicant::kInterfacePropertyDepth]
.writer().append_uint32(kDepthValue);
ScopedMockLog log;
EXPECT_CALL(log,
Log(logging::LOG_ERROR, _, EndsWith("no subject parameter.")));
EXPECT_FALSE(WPASupplicant::ExtractRemoteCertification(
- property_map, &subject, &depth));
+ property_map_, &subject, &depth));
EXPECT_EQ("", subject);
EXPECT_NE(kDepthValue, depth);
}
@@ -143,13 +56,12 @@
const char kSubjectName[] = "subject-name";
string subject;
uint32 depth = 0;
- PropertyMap property_map;
- property_map[WPASupplicant::kInterfacePropertySubject]
+ property_map_[WPASupplicant::kInterfacePropertySubject]
.writer().append_string(kSubjectName);
ScopedMockLog log;
EXPECT_CALL(log, Log(logging::LOG_ERROR, _, EndsWith("no depth parameter.")));
EXPECT_FALSE(WPASupplicant::ExtractRemoteCertification(
- property_map, &subject, &depth));
+ property_map_, &subject, &depth));
EXPECT_EQ("", subject);
EXPECT_EQ(0, depth);
}
@@ -159,13 +71,12 @@
string subject;
const uint32 kDepthValue = 100;
uint32 depth = 0;
- PropertyMap property_map;
- property_map[WPASupplicant::kInterfacePropertySubject]
+ property_map_[WPASupplicant::kInterfacePropertySubject]
.writer().append_string(kSubjectName);
- property_map[WPASupplicant::kInterfacePropertyDepth]
+ property_map_[WPASupplicant::kInterfacePropertyDepth]
.writer().append_uint32(kDepthValue);
EXPECT_TRUE(WPASupplicant::ExtractRemoteCertification(
- property_map, &subject, &depth));
+ property_map_, &subject, &depth));
EXPECT_EQ(kSubjectName, subject);
EXPECT_EQ(kDepthValue, depth);
}