| // Copyright 2018 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_WIFI_WIFI_SERVICE_H_ |
| #define SHILL_WIFI_WIFI_SERVICE_H_ |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "shill/event_dispatcher.h" |
| #include "shill/key_value_store.h" |
| #include "shill/refptr_types.h" |
| #include "shill/service.h" |
| |
| namespace shill { |
| |
| class CertificateFile; |
| class Error; |
| class Manager; |
| class WiFiProvider; |
| |
| class WiFiService : public Service { |
| public: |
| // TODO(pstew): Storage constants shouldn't need to be public |
| // crbug.com/208736 |
| static const char kStorageCredentialPassphrase[]; |
| static const char kStorageHiddenSSID[]; |
| static const char kStorageMode[]; |
| static const char kStorageSecurityClass[]; |
| static const char kStorageSSID[]; |
| |
| WiFiService(Manager* manager, |
| WiFiProvider* provider, |
| const std::vector<uint8_t>& ssid, |
| const std::string& mode, |
| const std::string& security_class, |
| bool hidden_ssid); |
| ~WiFiService(); |
| |
| // Inherited from Service. |
| bool Is8021x() const override; |
| |
| virtual void AddEndpoint(const WiFiEndpointConstRefPtr& endpoint); |
| virtual void RemoveEndpoint(const WiFiEndpointConstRefPtr& endpoint); |
| virtual int GetEndpointCount() const { return endpoints_.size(); } |
| |
| // Called to update the identity of the currently connected endpoint. |
| // To indicate that there is no currently connect endpoint, call with |
| // |endpoint| set to nullptr. |
| virtual void NotifyCurrentEndpoint(const WiFiEndpointConstRefPtr& endpoint); |
| // Called to inform of changes in the properties of an endpoint. |
| // (Not necessarily the currently connected endpoint.) |
| virtual void NotifyEndpointUpdated(const WiFiEndpointConstRefPtr& endpoint); |
| |
| // wifi_<MAC>_<BSSID>_<mode_string>_<security_string> |
| std::string GetStorageIdentifier() const override; |
| |
| // Validate |mode| against all valid and supported service modes. |
| static bool IsValidMode(const std::string& mode); |
| |
| // Validate |method| against all valid and supported security methods. |
| static bool IsValidSecurityMethod(const std::string& method); |
| |
| // Validate |security_class| against all valid and supported |
| // security classes. |
| static bool IsValidSecurityClass(const std::string& security_class); |
| |
| const std::string& mode() const { return mode_; } |
| const std::string& key_management() const { return GetEAPKeyManagement(); } |
| const std::vector<uint8_t>& ssid() const { return ssid_; } |
| const std::string& bssid() const { return bssid_; } |
| const std::vector<uint16_t>& frequency_list() const { |
| return frequency_list_; |
| } |
| uint16_t physical_mode() const { return physical_mode_; } |
| uint16_t frequency() const { return frequency_; } |
| const std::string& security() const { return security_; } |
| std::string security_class() const { return ComputeSecurityClass(security_); } |
| |
| // WiFi services can load from profile entries other than their current |
| // storage identifier. Override the methods from the parent Service |
| // class which pertain to whether this service may be loaded from |storage|. |
| std::string GetLoadableStorageIdentifier( |
| const StoreInterface& storage) const override; |
| bool IsLoadableFrom(const StoreInterface& storage) const override; |
| |
| // Override Storage methods from parent Service class. We will call |
| // the parent method. |
| bool Load(const StoreInterface* storage) override; |
| void MigrateDeprecatedStorage(StoreInterface* storage) override; |
| bool Save(StoreInterface* storage) override; |
| bool Unload() override; |
| |
| // Override SetState from parent Service class. We will call the |
| // parent method. |
| void SetState(ConnectState state) override; |
| |
| virtual bool HasEndpoints() const { return !endpoints_.empty(); } |
| bool IsVisible() const override; |
| bool IsSecurityMatch(const std::string& security) const; |
| |
| // Used by WiFi objects to indicate that the credentials for this network |
| // have been called into question. This method returns true if given this |
| // suspicion, if it is probable that indeed these credentials are likely |
| // to be incorrect. Credentials that have never been used before are |
| // considered suspect by default, while those which have been used |
| // successfully in the past must have this method called a number of times |
| // since the last time ResetSuspectedCredentialsFailures() was called. |
| virtual bool AddSuspectedCredentialFailure(); |
| virtual void ResetSuspectedCredentialFailures(); |
| |
| bool hidden_ssid() const { return hidden_ssid_; } |
| |
| void InitializeCustomMetrics() const; |
| void SendPostReadyStateMetrics( |
| int64_t time_resume_to_ready_milliseconds) const override; |
| |
| // Clear any cached credentials stored in wpa_supplicant related to |this|. |
| // This will disconnect this service if it is currently connected. |
| void ClearCachedCredentials(); |
| |
| // Override from parent Service class to correctly update connectability |
| // when the EAP credentials change for 802.1x networks. |
| void OnEapCredentialsChanged( |
| Service::UpdateCredentialsReason reason) override; |
| |
| // Called by WiFiService to reset state associated with prior success |
| // of a connection with particular EAP credentials or a passphrase. |
| void OnCredentialChange(Service::UpdateCredentialsReason reason); |
| |
| // Override from parent Service class to register hidden services once they |
| // have been configured. |
| void OnProfileConfigured() override; |
| |
| // Called by WiFiProvider to reset the WiFi device reference on shutdown. |
| virtual void ResetWiFi(); |
| |
| // Called by WiFi to retrieve configuration parameters for wpa_supplicant. |
| virtual KeyValueStore GetSupplicantConfigurationParameters() const; |
| |
| // "wpa", "rsn" and "psk" are equivalent from a configuration perspective. |
| // This function maps them all into "psk". |
| static std::string ComputeSecurityClass(const std::string& security); |
| |
| bool IsAutoConnectable(const char** reason) const override; |
| |
| std::string GetWiFiPassphrase(Error* error) override; |
| |
| // Signal level in dBm. If no current endpoint, returns |
| // std::numeric_limits<int>::min(). |
| int16_t SignalLevel() const; |
| |
| void set_expecting_disconnect(bool val) { expecting_disconnect_ = val; } |
| bool expecting_disconnect() const { return expecting_disconnect_; } |
| |
| void set_bgscan_string(const std::string& val) { bgscan_string_ = val; } |
| std::string bgscan_string() const { return bgscan_string_; } |
| |
| protected: |
| // Inherited from Service. |
| void OnConnect(Error* error) override; |
| void OnDisconnect(Error* error, const char* reason) override; |
| bool IsDisconnectable(Error* error) const override; |
| |
| void SetEAPKeyManagement(const std::string& key_management) override; |
| std::string GetTethering(Error* error) const override; |
| |
| private: |
| friend class WiFiServiceSecurityTest; |
| friend class WiFiServiceTest; // SetPassphrase |
| friend class WiFiServiceUpdateFromEndpointsTest; // SignalToStrength |
| FRIEND_TEST(MetricsTest, WiFiServicePostReady); |
| FRIEND_TEST(MetricsTest, WiFiServicePostReadyEAP); |
| FRIEND_TEST(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint); |
| FRIEND_TEST(WiFiServiceTest, AutoConnect); |
| FRIEND_TEST(WiFiServiceTest, ClearWriteOnlyDerivedProperty); // passphrase_ |
| FRIEND_TEST(WiFiServiceTest, ComputeCipher8021x); |
| FRIEND_TEST(WiFiServiceTest, ConnectTask8021x); |
| FRIEND_TEST(WiFiServiceTest, ConnectTaskDynamicWEP); |
| FRIEND_TEST(WiFiServiceTest, ConnectTaskPSK); |
| FRIEND_TEST(WiFiServiceTest, ConnectTaskRawPMK); |
| FRIEND_TEST(WiFiServiceTest, ConnectTaskWEP); |
| FRIEND_TEST(WiFiServiceTest, GetTethering); |
| FRIEND_TEST(WiFiServiceTest, IsAutoConnectable); |
| FRIEND_TEST(WiFiServiceTest, LoadHidden); |
| FRIEND_TEST(WiFiServiceTest, SetPassphraseForNonPassphraseService); |
| FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPassphrase); |
| FRIEND_TEST(WiFiServiceTest, LoadPassphraseClearCredentials); |
| FRIEND_TEST(WiFiServiceTest, SetPassphraseResetHasEverConnected); |
| FRIEND_TEST(WiFiServiceTest, SetPassphraseRemovesCachedCredentials); |
| FRIEND_TEST(WiFiServiceTest, SignalToStrength); // SignalToStrength |
| FRIEND_TEST(WiFiServiceTest, SuspectedCredentialFailure); |
| FRIEND_TEST(WiFiServiceTest, UpdateSecurity); // SetEAPKeyManagement |
| FRIEND_TEST(WiFiServiceTest, ChooseDevice); |
| |
| static const char kAutoConnNoEndpoint[]; |
| static const char kAnyDeviceAddress[]; |
| static const int kSuspectedCredentialFailureThreshold; |
| |
| // Override the base clase implementation, because we need to allow |
| // arguments that aren't base class methods. |
| void HelpRegisterConstDerivedString( |
| const std::string& name, std::string (WiFiService::*get)(Error* error)); |
| void HelpRegisterDerivedString( |
| const std::string& name, |
| std::string (WiFiService::*get)(Error* error), |
| bool (WiFiService::*set)(const std::string& value, Error* error)); |
| void HelpRegisterWriteOnlyDerivedString( |
| const std::string& name, |
| bool (WiFiService::*set)(const std::string& value, Error* error), |
| void (WiFiService::*clear)(Error* error), |
| const std::string* default_value); |
| void HelpRegisterDerivedUint16(const std::string& name, |
| uint16_t (WiFiService::*get)(Error* error), |
| bool (WiFiService::*set)(const uint16_t& value, |
| Error* error), |
| void (WiFiService::*clear)(Error* error)); |
| |
| RpcIdentifier GetDeviceRpcId(Error* error) const override; |
| |
| void ClearPassphrase(Error* error); |
| void UpdateConnectable(); |
| void UpdateFromEndpoints(); |
| void UpdateSecurity(); |
| |
| static CryptoAlgorithm ComputeCipher8021x( |
| const std::set<WiFiEndpointConstRefPtr>& endpoints); |
| static void ValidateWEPPassphrase(const std::string& passphrase, |
| Error* error); |
| static void ValidateWPAPassphrase(const std::string& passphrase, |
| Error* error); |
| static void ParseWEPPassphrase(const std::string& passphrase, |
| int* key_index, |
| std::vector<uint8_t>* password_bytes, |
| Error* error); |
| static void ParseWPAPassphrase(const std::string& passphrase, |
| std::vector<uint8_t>* passphrase_bytes, |
| Error* error); |
| static bool CheckWEPIsHex(const std::string& passphrase, Error* error); |
| static bool CheckWEPKeyIndex(const std::string& passphrase, Error* error); |
| static bool CheckWEPPrefix(const std::string& passphrase, Error* error); |
| |
| // Maps a signal value, in dBm, to a "strength" value, from |
| // |Service::kStrengthMin| to |Service:kStrengthMax|. |
| static uint8_t SignalToStrength(int16_t signal_dbm); |
| |
| // Create a default group name for this WiFi service. |
| std::string GetDefaultStorageIdentifier() const; |
| |
| // Return the security of this service. If visible, the security |
| // reported from the representative endpoint is returned. Otherwise |
| // the configured security for the service is returned. |
| std::string GetSecurity(Error* error); |
| |
| // Return the security class of this service. If visible, the |
| // security class of the representative endpoint is returned. |
| // Otherwise the configured security class for the service is |
| // returned. |
| // |
| // See also: ComputeSecurityClass. |
| std::string GetSecurityClass(Error* error); |
| |
| // Profile data for a WPA/RSN service can be stored under a number of |
| // different security types. These functions create different storage |
| // property lists based on whether they are saved with their generic |
| // "psk" name or if they use the (legacy) specific "wpa" or "rsn" names. |
| KeyValueStore GetStorageProperties() const; |
| |
| // Called from DBus and during Load to validate and apply a passphrase for |
| // this service. If the passphrase is successfully changed, UpdateConnectable |
| // and OnCredentialChange are both called and the method returns true. This |
| // method will return false if the passphrase cannot be set. If the |
| // passphrase is already set to the value of |passphrase|, this method will |
| // return false. If it is due to an error, |error| will be populated with the |
| // appropriate information. |
| bool SetPassphrase(const std::string& passphrase, Error* error); |
| |
| // Called by SetPassphrase and LoadPassphrase to perform the check on a |
| // passphrase change. |passphrase| is the new passphrase to be used for the |
| // service. If the new passphrase is not different from the existing |
| // passphrase, SetPassphraseInternal will return false. |reason| signals how |
| // the SetPassphraseInternal method was triggered. If the method was called |
| // from Load, the has_ever_connected flag will not be reset. If the method |
| // was called from SetPassphrase, has_ever_connected will be set to false. |
| bool SetPassphraseInternal(const std::string& passphrase, |
| Service::UpdateCredentialsReason reason); |
| |
| // Select a WiFi device (e.g, for connecting a hidden service with no |
| // endpoints). |
| WiFiRefPtr ChooseDevice(); |
| |
| void SetWiFi(const WiFiRefPtr& new_wifi); |
| |
| // Properties |
| std::string passphrase_; |
| bool need_passphrase_; |
| // The current security mode. May be updated based on detected BSS. |
| // TODO(b/157935328): consider factoring this out into a class, to hide some |
| // of the overlap (but not identical) nature of Security and SecurityClass. |
| std::string security_; |
| // TODO(cmasone): see if the below can be pulled from the endpoint associated |
| // with this service instead. |
| const std::string mode_; |
| bool hidden_ssid_; |
| uint16_t frequency_; |
| std::vector<uint16_t> frequency_list_; |
| uint16_t physical_mode_; |
| // The raw dBm signal strength from the associated endpoint. |
| int16_t raw_signal_strength_; |
| std::string hex_ssid_; |
| std::string storage_identifier_; |
| std::string bssid_; |
| Stringmap vendor_information_; |
| // The country code reported by the current endpoint. |
| std::string country_code_; |
| // If |security_| == kSecurity8021x, the crypto algorithm being used. |
| // (Otherwise, crypto algorithm is implied by |security_|.) |
| CryptoAlgorithm cipher_8021x_; |
| |
| // Track the number of consecutive times our current credentials have |
| // been called into question. |
| int suspected_credential_failures_; |
| |
| // Track whether or not we've warned about large signal values. |
| // Used to avoid spamming the log. |
| static bool logged_signal_warning; |
| |
| WiFiRefPtr wifi_; |
| std::set<WiFiEndpointConstRefPtr> endpoints_; |
| WiFiEndpointConstRefPtr current_endpoint_; |
| const std::vector<uint8_t> ssid_; |
| // Flag indicating if service disconnect is initiated by user for |
| // connecting to other service. |
| bool expecting_disconnect_; |
| // The background scan configuration parameters. |
| std::string bgscan_string_; |
| std::unique_ptr<CertificateFile> certificate_file_; |
| // Bare pointer is safe because WiFi service instances are owned by |
| // the WiFiProvider and are guaranteed to be deallocated by the time |
| // the WiFiProvider is. |
| WiFiProvider* provider_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WiFiService); |
| }; |
| |
| } // namespace shill |
| |
| #endif // SHILL_WIFI_WIFI_SERVICE_H_ |