1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#ifndef SHILL_WIFI_WIFI_SERVICE_H_
18#define SHILL_WIFI_WIFI_SERVICE_H_
19
20#include <memory>
21#include <set>
22#include <string>
23#include <vector>
24
25#include "shill/event_dispatcher.h"
26#include "shill/key_value_store.h"
27#include "shill/refptr_types.h"
28#include "shill/service.h"
29
30namespace shill {
31
32class CertificateFile;
33class ControlInterface;
34class EventDispatcher;
35class Error;
36class Manager;
37class Metrics;
38class WiFiProvider;
39
40class WiFiService : public Service {
41 public:
42  // TODO(pstew): Storage constants shouldn't need to be public
43  // crbug.com/208736
44  static const char kStorageHiddenSSID[];
45  static const char kStorageMode[];
46  static const char kStoragePassphrase[];
47  static const char kStorageSecurity[];
48  static const char kStorageSecurityClass[];
49  static const char kStorageSSID[];
50  static const char kStoragePreferredDevice[];
51  static const char kStorageRoamThreshold[];
52  static const char kStorageRoamThresholdSet[];
53
54  WiFiService(ControlInterface* control_interface,
55              EventDispatcher* dispatcher,
56              Metrics* metrics,
57              Manager* manager,
58              WiFiProvider* provider,
59              const std::vector<uint8_t>& ssid,
60              const std::string& mode,
61              const std::string& security,
62              bool hidden_ssid);
63  ~WiFiService();
64
65  // Inherited from Service.
66  void Connect(Error* error, const char* reason) override;
67  void Disconnect(Error* error, const char* reason) override;
68  bool Is8021x() const override;
69
70  virtual void AddEndpoint(const WiFiEndpointConstRefPtr& endpoint);
71  virtual void RemoveEndpoint(const WiFiEndpointConstRefPtr& endpoint);
72  virtual int GetEndpointCount() const { return endpoints_.size(); }
73
74  // Called to update the identity of the currently connected endpoint.
75  // To indicate that there is no currently connect endpoint, call with
76  // |endpoint| set to nullptr.
77  virtual void NotifyCurrentEndpoint(const WiFiEndpointConstRefPtr& endpoint);
78  // Called to inform of changes in the properties of an endpoint.
79  // (Not necessarily the currently connected endpoint.)
80  virtual void NotifyEndpointUpdated(const WiFiEndpointConstRefPtr& endpoint);
81
82  // wifi_<MAC>_<BSSID>_<mode_string>_<security_string>
83  std::string GetStorageIdentifier() const override;
84  static bool ParseStorageIdentifier(const std::string& storage_name,
85                                     std::string* address,
86                                     std::string* mode,
87                                     std::string* security);
88
89  // Iterate over |storage| looking for WiFi servces with "old-style"
90  // properties that don't include explicit type/mode/security, and add
91  // these properties.  Returns true if any entries were fixed.
92  static bool FixupServiceEntries(StoreInterface* storage);
93
94  // Validate |mode| against all valid and supported service modes.
95  static bool IsValidMode(const std::string& mode);
96
97  // Validate |method| against all valid and supported security methods.
98  static bool IsValidSecurityMethod(const std::string& method);
99
100  // Validate |security_class| against all valid and supported
101  // security classes.
102  static bool IsValidSecurityClass(const std::string& security_class);
103
104  const std::string& mode() const { return mode_; }
105  const std::string& key_management() const { return GetEAPKeyManagement(); }
106  const std::vector<uint8_t>& ssid() const { return ssid_; }
107  const std::string& bssid() const { return bssid_; }
108  const std::vector<uint16_t>& frequency_list() const {
109    return frequency_list_;
110  }
111  uint16_t physical_mode() const { return physical_mode_; }
112  uint16_t frequency() const { return frequency_; }
113
114  // WiFi services can load from profile entries other than their current
115  // storage identifier.  Override the methods from the parent Service
116  // class which pertain to whether this service may be loaded from |storage|.
117  std::string GetLoadableStorageIdentifier(
118      const StoreInterface& storage) const override;
119  bool IsLoadableFrom(const StoreInterface& storage) const override;
120
121  // Override Load and Save from parent Service class.  We will call
122  // the parent method.
123  bool Load(StoreInterface* storage) override;
124  bool Save(StoreInterface* storage) override;
125  bool Unload() override;
126
127  // Override SetState from parent Service class.  We will call the
128  // parent method.
129  void SetState(ConnectState state) override;
130
131  virtual bool HasEndpoints() const { return !endpoints_.empty(); }
132  bool IsVisible() const override;
133  bool IsSecurityMatch(const std::string& security) const;
134
135  // Used by WiFi objects to indicate that the credentials for this network
136  // have been called into question.  This method returns true if given this
137  // suspicion, if it is probable that indeed these credentials are likely
138  // to be incorrect.  Credentials that have never been used before are
139  // considered suspect by default, while those which have been used
140  // successfully in the past must have this method called a number of times
141  // since the last time ResetSuspectedCredentialsFailures() was called.
142  virtual bool AddSuspectedCredentialFailure();
143  virtual void ResetSuspectedCredentialFailures();
144
145  bool hidden_ssid() const { return hidden_ssid_; }
146  bool ieee80211w_required() const { return ieee80211w_required_; }
147
148  void InitializeCustomMetrics() const;
149  void SendPostReadyStateMetrics(
150      int64_t time_resume_to_ready_milliseconds) const override;
151
152  // Clear any cached credentials stored in wpa_supplicant related to |this|.
153  // This will disconnect this service if it is currently connected.
154  void ClearCachedCredentials();
155
156  // Override from parent Service class to correctly update connectability
157  // when the EAP credentials change for 802.1x networks.
158  void OnEapCredentialsChanged(
159      Service::UpdateCredentialsReason reason) override;
160
161  // Called by WiFiService to reset state associated with prior success
162  // of a connection with particular EAP credentials or a passphrase.
163  void OnCredentialChange(Service::UpdateCredentialsReason reason);
164
165  // Override from parent Service class to register hidden services once they
166  // have been configured.
167  void OnProfileConfigured() override;
168
169  // Called by WiFiProvider to reset the WiFi device reference on shutdown.
170  virtual void ResetWiFi();
171
172  // Called by WiFi to retrieve configuration parameters for wpa_supplicant.
173  virtual KeyValueStore GetSupplicantConfigurationParameters() const;
174
175  // "wpa", "rsn" and "psk" are equivalent from a configuration perspective.
176  // This function maps them all into "psk".
177  static std::string ComputeSecurityClass(const std::string& security);
178
179  bool IsAutoConnectable(const char** reason) const override;
180
181  // Signal level in dBm.  If no current endpoint, returns
182  // std::numeric_limits<int>::min().
183  int16_t SignalLevel() const;
184
185  void set_expecting_disconnect(bool val) { expecting_disconnect_ = val; }
186  bool expecting_disconnect() const { return expecting_disconnect_; }
187
188  uint16_t roam_threshold_db() { return roam_threshold_db_; }
189  bool roam_threshold_db_set() { return roam_threshold_db_set_; }
190
191 protected:
192  void SetEAPKeyManagement(const std::string& key_management) override;
193  std::string GetTethering(Error* error) const override;
194
195 private:
196  friend class WiFiServiceSecurityTest;
197  friend class WiFiServiceTest;  // SetPassphrase
198  friend class WiFiServiceUpdateFromEndpointsTest;  // SignalToStrength
199  FRIEND_TEST(MetricsTest, WiFiServicePostReady);
200  FRIEND_TEST(MetricsTest, WiFiServicePostReadyAdHoc);
201  FRIEND_TEST(MetricsTest, WiFiServicePostReadyEAP);
202  FRIEND_TEST(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint);
203  FRIEND_TEST(WiFiMainTest, RoamThresholdProperty);
204  FRIEND_TEST(WiFiProviderTest, OnEndpointAddedWithSecurity);  // security_
205  FRIEND_TEST(WiFiServiceTest, AutoConnect);
206  FRIEND_TEST(WiFiServiceTest, ClearWriteOnlyDerivedProperty);  // passphrase_
207  FRIEND_TEST(WiFiServiceTest, ComputeCipher8021x);
208  FRIEND_TEST(WiFiServiceTest, ConnectTask8021x);
209  FRIEND_TEST(WiFiServiceTest, ConnectTaskDynamicWEP);
210  FRIEND_TEST(WiFiServiceTest, ConnectTaskPSK);
211  FRIEND_TEST(WiFiServiceTest, ConnectTaskRSN);
212  FRIEND_TEST(WiFiServiceTest, ConnectTaskWEP);
213  FRIEND_TEST(WiFiServiceTest, ConnectTaskWPA);
214  FRIEND_TEST(WiFiServiceTest, ConnectTaskWPA80211w);
215  FRIEND_TEST(WiFiServiceTest, GetTethering);
216  FRIEND_TEST(WiFiServiceTest, IsAutoConnectable);
217  FRIEND_TEST(WiFiServiceTest, LoadHidden);
218  FRIEND_TEST(WiFiServiceTest, SetPassphraseForNonPassphraseService);
219  FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPassphrase);
220  FRIEND_TEST(WiFiServiceTest, LoadPassphraseClearCredentials);
221  FRIEND_TEST(WiFiServiceTest, SecurityFromCurrentEndpoint);  // GetSecurity
222  FRIEND_TEST(WiFiServiceTest, SetPassphraseResetHasEverConnected);
223  FRIEND_TEST(WiFiServiceTest, SetPassphraseRemovesCachedCredentials);
224  FRIEND_TEST(WiFiServiceTest, SignalToStrength);  // SignalToStrength
225  FRIEND_TEST(WiFiServiceTest, SuspectedCredentialFailure);
226  FRIEND_TEST(WiFiServiceTest, UpdateSecurity);  // SetEAPKeyManagement
227  FRIEND_TEST(WiFiServiceTest, ConnectWithPreferredDevice);
228  FRIEND_TEST(WiFiServiceTest, ConfigurePreferredDevice);
229  FRIEND_TEST(WiFiServiceTest, LoadAndUnloadPreferredDevice);
230  FRIEND_TEST(WiFiServiceTest, ChooseDevice);
231  FRIEND_TEST(WiFiServiceUpdateFromEndpointsTest,
232              AddEndpointWithPreferredDevice);
233  FRIEND_TEST(WiFiServiceTest, SaveLoadRoamThreshold);
234
235  static const char kAutoConnNoEndpoint[];
236  static const char kAnyDeviceAddress[];
237  static const int kSuspectedCredentialFailureThreshold;
238
239  // Override the base clase implementation, because we need to allow
240  // arguments that aren't base class methods.
241  void HelpRegisterConstDerivedString(
242      const std::string& name,
243      std::string(WiFiService::*get)(Error* error));
244  void HelpRegisterDerivedString(
245      const std::string& name,
246      std::string(WiFiService::*get)(Error* error),
247      bool(WiFiService::*set)(const std::string& value, Error* error));
248  void HelpRegisterWriteOnlyDerivedString(
249      const std::string& name,
250      bool(WiFiService::*set)(const std::string& value, Error* error),
251      void(WiFiService::*clear)(Error* error),
252      const std::string* default_value);
253  void HelpRegisterDerivedUint16(
254      const std::string& name,
255      uint16_t(WiFiService::*get)(Error* error),
256      bool(WiFiService::*set)(const uint16_t& value, Error* error),
257      void(WiFiService::*clear)(Error* error));
258
259  std::string GetDeviceRpcId(Error* error) const override;
260
261  void ClearPassphrase(Error* error);
262  void UpdateConnectable();
263  void UpdateFromEndpoints();
264  void UpdateSecurity();
265
266  static CryptoAlgorithm ComputeCipher8021x(
267      const std::set<WiFiEndpointConstRefPtr>& endpoints);
268  static void ValidateWEPPassphrase(const std::string& passphrase,
269                                    Error* error);
270  static void ValidateWPAPassphrase(const std::string& passphrase,
271                                    Error* error);
272  static void ParseWEPPassphrase(const std::string& passphrase,
273                                 int* key_index,
274                                 std::vector<uint8_t>* password_bytes,
275                                 Error* error);
276  static bool CheckWEPIsHex(const std::string& passphrase, Error* error);
277  static bool CheckWEPKeyIndex(const std::string& passphrase, Error* error);
278  static bool CheckWEPPrefix(const std::string& passphrase, Error* error);
279
280  // Maps a signal value, in dBm, to a "strength" value, from
281  // |Service::kStrengthMin| to |Service:kStrengthMax|.
282  static uint8_t SignalToStrength(int16_t signal_dbm);
283
284  // Create a default group name for this WiFi service.
285  std::string GetDefaultStorageIdentifier() const;
286
287  // Return the security of this service.  If connected, the security
288  // reported from the currently connected endpoint is returned.  Otherwise
289  // the configured security for the service is returned.
290  std::string GetSecurity(Error* error);
291
292  // Return the security class of this service.  If connected, the
293  // security class of the currently connected endpoint is returned.
294  // Otherwise the configured security class for the service is
295  // returned.
296  //
297  // See also: ComputeSecurityClass.
298  std::string GetSecurityClass(Error* error);
299
300  // Profile data for a WPA/RSN service can be stored under a number of
301  // different security types.  These functions create different storage
302  // property lists based on whether they are saved with their generic
303  // "psk" name or if they use the (legacy) specific "wpa" or "rsn" names.
304  KeyValueStore GetStorageProperties() const;
305
306  // Called from DBus and during Load to validate and apply a passphrase for
307  // this service.  If the passphrase is successfully changed, UpdateConnectable
308  // and OnCredentialChange are both called and the method returns true.  This
309  // method will return false if the passphrase cannot be set.  If the
310  // passphrase is already set to the value of |passphrase|, this method will
311  // return false.  If it is due to an error, |error| will be populated with the
312  // appropriate information.
313  bool SetPassphrase(const std::string& passphrase, Error* error);
314
315  // Called by SetPassphrase and LoadPassphrase to perform the check on a
316  // passphrase change.  |passphrase| is the new passphrase to be used for the
317  // service.  If the new passphrase is not different from the existing
318  // passphrase, SetPassphraseInternal will return false.  |reason| signals how
319  // the SetPassphraseInternal method was triggered.  If the method was called
320  // from Load, the has_ever_connected flag will not be reset.  If the method
321  // was called from SetPassphrase, has_ever_connected will be set to false.
322  bool SetPassphraseInternal(const std::string& passphrase,
323                             Service::UpdateCredentialsReason reason);
324
325  // Select a WiFi device (e.g, for connecting a hidden service with no
326  // endpoints).
327  WiFiRefPtr ChooseDevice();
328
329  std::string GetPreferredDevice(Error* error);
330  // Called from DBus and during load to apply the preferred device for this
331  // service.
332  bool SetPreferredDevice(const std::string& device_name, Error* error);
333
334  void SetWiFi(const WiFiRefPtr& new_wifi);
335
336  // This method can't be 'const' because it is passed to
337  // HelpRegisterDerivedUint16, which doesn't take const methods.
338  uint16_t GetRoamThreshold(Error* error) /*const*/;
339  bool SetRoamThreshold(const uint16_t& threshold, Error* error);
340  void ClearRoamThreshold(Error* error);
341
342  // Properties
343  std::string passphrase_;
344  bool need_passphrase_;
345  const std::string security_;
346  // TODO(cmasone): see if the below can be pulled from the endpoint associated
347  // with this service instead.
348  const std::string mode_;
349  std::string auth_mode_;
350  bool hidden_ssid_;
351  uint16_t frequency_;
352  std::vector<uint16_t> frequency_list_;
353  uint16_t physical_mode_;
354  // Preferred device to use for connecting to this service.
355  std::string preferred_device_;
356  // The raw dBm signal strength from the associated endpoint.
357  int16_t raw_signal_strength_;
358  std::string hex_ssid_;
359  std::string storage_identifier_;
360  std::string bssid_;
361  Stringmap vendor_information_;
362  // The country code reported by the current endpoint.
363  std::string country_code_;
364  // If |security_| == kSecurity8021x, the crypto algorithm being used.
365  // (Otherwise, crypto algorithm is implied by |security_|.)
366  CryptoAlgorithm cipher_8021x_;
367
368  // Track the number of consecutive times our current credentials have
369  // been called into question.
370  int suspected_credential_failures_;
371
372  // Track whether or not we've warned about large signal values.
373  // Used to avoid spamming the log.
374  static bool logged_signal_warning;
375
376  WiFiRefPtr wifi_;
377  std::set<WiFiEndpointConstRefPtr> endpoints_;
378  WiFiEndpointConstRefPtr current_endpoint_;
379  const std::vector<uint8_t> ssid_;
380  // Track whether IEEE 802.11w (Protected Management Frame) support is
381  // mandated by one or more endpoints we have seen that provide this service.
382  bool ieee80211w_required_;
383  // Flag indicating if service disconnect is initiated by user for
384  // connecting to other service.
385  bool expecting_disconnect_;
386  std::unique_ptr<CertificateFile> certificate_file_;
387  uint16_t roam_threshold_db_;
388  bool roam_threshold_db_set_;
389  // Bare pointer is safe because WiFi service instances are owned by
390  // the WiFiProvider and are guaranteed to be deallocated by the time
391  // the WiFiProvider is.
392  WiFiProvider* provider_;
393
394  DISALLOW_COPY_AND_ASSIGN(WiFiService);
395};
396
397}  // namespace shill
398
399#endif  // SHILL_WIFI_WIFI_SERVICE_H_
400