OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/chromeos/cros/network_library.h" | |
6 | |
7 #include "base/chromeos/chromeos_version.h" | |
8 #include "base/i18n/icu_encoding_detection.h" | |
9 #include "base/i18n/icu_string_conversions.h" | |
10 #include "base/i18n/time_formatting.h" | |
11 #include "base/json/json_writer.h" // for debug output only. | |
12 #include "base/strings/string_number_conversions.h" | |
13 #include "base/strings/utf_string_conversion_utils.h" | |
14 #include "chrome/browser/chromeos/cros/native_network_constants.h" | |
15 #include "chrome/browser/chromeos/cros/native_network_parser.h" | |
16 #include "chrome/browser/chromeos/cros/network_library_impl_cros.h" | |
17 #include "chrome/browser/chromeos/cros/network_library_impl_stub.h" | |
18 #include "chrome/browser/chromeos/enrollment_dialog_view.h" | |
19 #include "chrome/common/net/x509_certificate_model.h" | |
20 #include "chromeos/network/certificate_pattern.h" | |
21 #include "chromeos/network/client_cert_util.h" | |
22 #include "chromeos/network/cros_network_functions.h" | |
23 #include "chromeos/network/network_state_handler.h" | |
24 #include "chromeos/network/onc/onc_utils.h" | |
25 #include "content/public/browser/browser_thread.h" | |
26 #include "grit/ash_strings.h" | |
27 #include "grit/generated_resources.h" | |
28 #include "net/base/url_util.h" | |
29 #include "third_party/cros_system_api/dbus/service_constants.h" | |
30 #include "ui/base/l10n/l10n_util.h" | |
31 | |
32 using content::BrowserThread; | |
33 | |
34 //////////////////////////////////////////////////////////////////////////////// | |
35 // Implementation notes. | |
36 // NetworkLibraryImpl manages a series of classes that describe network devices | |
37 // and services: | |
38 // | |
39 // NetworkDevice: e.g. ethernet, wifi modem, cellular modem | |
40 // device_map_: canonical map<path, NetworkDevice*> for devices | |
41 // | |
42 // Network: a network service ("network"). | |
43 // network_map_: canonical map<path, Network*> for all visible networks. | |
44 // EthernetNetwork | |
45 // ethernet_: EthernetNetwork* to the active ethernet network in network_map_. | |
46 // WirelessNetwork: a WiFi or Cellular Network. | |
47 // WifiNetwork | |
48 // active_wifi_: WifiNetwork* to the active wifi network in network_map_. | |
49 // wifi_networks_: ordered vector of WifiNetwork* entries in network_map_, | |
50 // in descending order of importance. | |
51 // CellularNetwork | |
52 // active_cellular_: Cellular version of wifi_. | |
53 // cellular_networks_: Cellular version of wifi_. | |
54 // network_unique_id_map_: map<unique_id, Network*> for all visible networks. | |
55 // remembered_network_map_: a canonical map<path, Network*> for all networks | |
56 // remembered in the active Profile ("favorites"). | |
57 // remembered_network_unique_id_map_: map<unique_id, Network*> for all | |
58 // remembered networks. | |
59 // remembered_wifi_networks_: ordered vector of WifiNetwork* entries in | |
60 // remembered_network_map_, in descending order of preference. | |
61 // remembered_virtual_networks_: ordered vector of VirtualNetwork* entries in | |
62 // remembered_network_map_, in descending order of preference. | |
63 // | |
64 // network_manager_monitor_: a handle to the libcros network Manager handler. | |
65 // NetworkManagerStatusChanged: This handles all messages from the Manager. | |
66 // Messages are parsed here and the appropriate updates are then requested. | |
67 // | |
68 // UpdateNetworkServiceList: This is the primary Manager handler. It handles | |
69 // the "Services" message which list all visible networks. The handler | |
70 // rebuilds the network lists without destroying existing Network structures, | |
71 // then requests neccessary updates to be fetched asynchronously from | |
72 // libcros (RequestNetworkServiceProperties). | |
73 // | |
74 // TODO(stevenjb): Document cellular data plan handlers. | |
75 // | |
76 // AddNetworkObserver: Adds an observer for a specific network. | |
77 // UpdateNetworkStatus: This handles changes to a monitored service, typically | |
78 // changes to transient states like Strength. (Note: also updates State). | |
79 // | |
80 // AddNetworkDeviceObserver: Adds an observer for a specific device. | |
81 // Will be called on any device property change. | |
82 // UpdateNetworkDeviceStatus: Handles changes to a monitored device, like | |
83 // SIM lock state and updates device state. | |
84 // | |
85 // All *Pin(...) methods use internal callback that would update cellular | |
86 // device state once async call is completed and notify all device observers. | |
87 // | |
88 //////////////////////////////////////////////////////////////////////////////// | |
89 | |
90 namespace chromeos { | |
91 | |
92 namespace { | |
93 | |
94 static NetworkLibrary* g_network_library = NULL; | |
95 | |
96 // Default value of the SIM unlock retries count. It is updated to the real | |
97 // retries count once cellular device with SIM card is initialized. | |
98 // If cellular device doesn't have SIM card, then retries are never used. | |
99 const int kDefaultSimUnlockRetriesCount = 999; | |
100 | |
101 //////////////////////////////////////////////////////////////////////////////// | |
102 // Misc. | |
103 | |
104 // Erase the memory used by a string, then clear it. | |
105 void WipeString(std::string* str) { | |
106 str->assign(str->size(), '\0'); | |
107 str->clear(); | |
108 } | |
109 | |
110 bool EnsureRunningOnChromeOS() { | |
111 if (!base::chromeos::IsRunningOnChromeOS()) { | |
112 return false; | |
113 } else { | |
114 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) | |
115 << "chromeos_network calls made from non UI thread!"; | |
116 return true; | |
117 } | |
118 } | |
119 | |
120 void ValidateUTF8(const std::string& str, std::string* output) { | |
121 output->clear(); | |
122 | |
123 for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) { | |
124 uint32 code_point_out; | |
125 bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(), | |
126 &index, &code_point_out); | |
127 if (is_unicode_char && (code_point_out >= 0x20)) | |
128 base::WriteUnicodeCharacter(code_point_out, output); | |
129 else | |
130 // Puts REPLACEMENT CHARACTER (U+FFFD) if character is not readable UTF-8 | |
131 base::WriteUnicodeCharacter(0xFFFD, output); | |
132 } | |
133 } | |
134 | |
135 std::string ConnectionStateString(ConnectionState state) { | |
136 switch (state) { | |
137 case STATE_UNKNOWN: | |
138 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNKNOWN); | |
139 case STATE_IDLE: | |
140 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_IDLE); | |
141 case STATE_CARRIER: | |
142 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CARRIER); | |
143 case STATE_ASSOCIATION: | |
144 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_ASSOCIATION); | |
145 case STATE_CONFIGURATION: | |
146 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_CONFIGURATION); | |
147 case STATE_READY: | |
148 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_READY); | |
149 case STATE_DISCONNECT: | |
150 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_DISCONNECT); | |
151 case STATE_FAILURE: | |
152 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_FAILURE); | |
153 case STATE_ACTIVATION_FAILURE: | |
154 return l10n_util::GetStringUTF8( | |
155 IDS_CHROMEOS_NETWORK_STATE_ACTIVATION_FAILURE); | |
156 case STATE_PORTAL: | |
157 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_PORTAL); | |
158 case STATE_ONLINE: | |
159 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_ONLINE); | |
160 case STATE_CONNECT_REQUESTED: | |
161 return l10n_util::GetStringUTF8( | |
162 IDS_CHROMEOS_NETWORK_STATE_CONNECT_REQUESTED); | |
163 } | |
164 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED); | |
165 } | |
166 | |
167 } // namespace | |
168 | |
169 //////////////////////////////////////////////////////////////////////////////// | |
170 // FoundCellularNetwork | |
171 | |
172 FoundCellularNetwork::FoundCellularNetwork() {} | |
173 | |
174 FoundCellularNetwork::~FoundCellularNetwork() {} | |
175 | |
176 //////////////////////////////////////////////////////////////////////////////// | |
177 // NetworkDevice | |
178 | |
179 NetworkDevice::NetworkDevice(const std::string& device_path) | |
180 : device_path_(device_path), | |
181 type_(TYPE_UNKNOWN), | |
182 scanning_(false), | |
183 sim_lock_state_(SIM_UNKNOWN), | |
184 sim_retries_left_(kDefaultSimUnlockRetriesCount), | |
185 sim_pin_required_(SIM_PIN_REQUIRE_UNKNOWN), | |
186 sim_present_(false), | |
187 powered_(false), | |
188 prl_version_(0), | |
189 data_roaming_allowed_(false), | |
190 support_network_scan_(false), | |
191 device_parser_(new NativeNetworkDeviceParser) { | |
192 } | |
193 | |
194 NetworkDevice::~NetworkDevice() {} | |
195 | |
196 void NetworkDevice::SetNetworkDeviceParser(NetworkDeviceParser* parser) { | |
197 device_parser_.reset(parser); | |
198 } | |
199 | |
200 void NetworkDevice::ParseInfo(const DictionaryValue& info) { | |
201 if (device_parser_.get()) | |
202 device_parser_->UpdateDeviceFromInfo(info, this); | |
203 } | |
204 | |
205 bool NetworkDevice::UpdateStatus(const std::string& key, | |
206 const base::Value& value, | |
207 PropertyIndex* index) { | |
208 if (device_parser_.get()) | |
209 return device_parser_->UpdateStatus(key, value, this, index); | |
210 return false; | |
211 } | |
212 | |
213 //////////////////////////////////////////////////////////////////////////////// | |
214 // Network | |
215 | |
216 Network::Network(const std::string& service_path, | |
217 ConnectionType type) | |
218 : state_(STATE_UNKNOWN), | |
219 error_(ERROR_NO_ERROR), | |
220 connectable_(true), | |
221 user_connect_state_(USER_CONNECT_NONE), | |
222 is_active_(false), | |
223 priority_(kPriorityNotSet), | |
224 auto_connect_(false), | |
225 save_credentials_(false), | |
226 priority_order_(0), | |
227 added_(false), | |
228 notify_failure_(false), | |
229 profile_type_(PROFILE_NONE), | |
230 service_path_(service_path), | |
231 type_(type) { | |
232 } | |
233 | |
234 Network::~Network() { | |
235 } | |
236 | |
237 void Network::SetNetworkParser(NetworkParser* parser) { | |
238 network_parser_.reset(parser); | |
239 } | |
240 | |
241 // static | |
242 Network* Network::CreateForTesting(ConnectionType type) { | |
243 return new Network("fake_service_path", type); | |
244 } | |
245 | |
246 void Network::SetState(ConnectionState new_state) { | |
247 if (new_state == state_) | |
248 return; | |
249 if (state_ == STATE_CONNECT_REQUESTED && new_state == STATE_IDLE) { | |
250 // CONNECT_REQUESTED is set internally. Shill does not update the | |
251 // state immediately, so ignore any Idle state updates sent while a | |
252 // connection attempt is in progress. | |
253 VLOG(2) << "Ignoring idle state change after connection request."; | |
254 return; | |
255 } | |
256 ConnectionState old_state = state_; | |
257 VLOG(2) << "Entering new state: " << ConnectionStateString(new_state); | |
258 state_ = new_state; | |
259 if (new_state == STATE_FAILURE) { | |
260 VLOG(1) << service_path() << ": Detected Failure state."; | |
261 if (old_state != STATE_UNKNOWN && old_state != STATE_IDLE && | |
262 (type() != TYPE_CELLULAR || | |
263 user_connect_state() == USER_CONNECT_STARTED)) { | |
264 // New failure, the user needs to be notified. | |
265 // Transition STATE_IDLE -> STATE_FAILURE sometimes happens on resume | |
266 // but is not an actual failure as network device is not ready yet. | |
267 // For Cellular we only show failure notifications if user initiated. | |
268 notify_failure_ = true; | |
269 // Normally error_ should be set, but if it is not we need to set it to | |
270 // something here so that the retry logic will be triggered. | |
271 if (error_ == ERROR_NO_ERROR) { | |
272 VLOG(2) << "Detected NO_ERROR error state. Setting to UNKNOWN."; | |
273 error_ = ERROR_UNKNOWN; | |
274 } | |
275 } | |
276 if (user_connect_state() == USER_CONNECT_STARTED) | |
277 set_user_connect_state(USER_CONNECT_FAILED); | |
278 } else if (new_state == STATE_IDLE && IsConnectingState(old_state) && | |
279 user_connect_state() == USER_CONNECT_STARTED) { | |
280 // If we requested a connect and never went through a connected state, | |
281 // treat it as a failure. | |
282 VLOG(1) << service_path() << ": Inferring Failure state."; | |
283 notify_failure_ = true; | |
284 error_ = ERROR_UNKNOWN; | |
285 if (user_connect_state() == USER_CONNECT_STARTED) | |
286 set_user_connect_state(USER_CONNECT_FAILED); | |
287 } else if (new_state != STATE_UNKNOWN) { | |
288 notify_failure_ = false; | |
289 // State changed, so refresh IP address. | |
290 InitIPAddress(); | |
291 if (user_connect_state() == USER_CONNECT_STARTED) { | |
292 if (IsConnectedState(new_state)) { | |
293 set_user_connect_state(USER_CONNECT_CONNECTED); | |
294 } else if (!IsConnectingState(new_state)) { | |
295 LOG(WARNING) << "Connection started and State -> " << GetStateString(); | |
296 set_user_connect_state(USER_CONNECT_FAILED); | |
297 } | |
298 } | |
299 } | |
300 VLOG(1) << name() << ".State [" << service_path() << "]: " << GetStateString() | |
301 << " (was: " << ConnectionStateString(old_state) << ")"; | |
302 } | |
303 | |
304 void Network::SetError(ConnectionError error) { | |
305 error_ = error; | |
306 if (error == ERROR_NO_ERROR) | |
307 notify_failure_ = false; | |
308 } | |
309 | |
310 void Network::SetName(const std::string& name) { | |
311 std::string name_utf8; | |
312 ValidateUTF8(name, &name_utf8); | |
313 set_name(name_utf8); | |
314 } | |
315 | |
316 void Network::ParseInfo(const DictionaryValue& info) { | |
317 if (network_parser_.get()) | |
318 network_parser_->UpdateNetworkFromInfo(info, this); | |
319 } | |
320 | |
321 void Network::EraseCredentials() { | |
322 } | |
323 | |
324 void Network::CalculateUniqueId() { | |
325 unique_id_ = name_; | |
326 } | |
327 | |
328 bool Network::RequiresUserProfile() const { | |
329 return false; | |
330 } | |
331 | |
332 void Network::CopyCredentialsFromRemembered(Network* remembered) { | |
333 } | |
334 | |
335 void Network::SetEnrollmentDelegate(EnrollmentDelegate* delegate) { | |
336 enrollment_delegate_.reset(delegate); | |
337 } | |
338 | |
339 void Network::SetValueProperty(const char* prop, const base::Value& value) { | |
340 DCHECK(prop); | |
341 if (!EnsureRunningOnChromeOS()) | |
342 return; | |
343 CrosSetNetworkServiceProperty(service_path_, prop, value); | |
344 // Ensure NetworkStateHandler properties are up-to-date. | |
345 if (NetworkHandler::IsInitialized()) { | |
346 NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( | |
347 service_path()); | |
348 } | |
349 } | |
350 | |
351 void Network::ClearProperty(const char* prop) { | |
352 DCHECK(prop); | |
353 if (!EnsureRunningOnChromeOS()) | |
354 return; | |
355 CrosClearNetworkServiceProperty(service_path_, prop); | |
356 // Ensure NetworkStateHandler properties are up-to-date. | |
357 if (NetworkHandler::IsInitialized()) { | |
358 NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( | |
359 service_path()); | |
360 } | |
361 } | |
362 | |
363 void Network::SetStringProperty( | |
364 const char* prop, const std::string& str, std::string* dest) { | |
365 if (dest) | |
366 *dest = str; | |
367 SetValueProperty(prop, base::StringValue(str)); | |
368 } | |
369 | |
370 void Network::SetOrClearStringProperty(const char* prop, | |
371 const std::string& str, | |
372 std::string* dest) { | |
373 if (str.empty()) { | |
374 ClearProperty(prop); | |
375 if (dest) | |
376 dest->clear(); | |
377 } else { | |
378 SetStringProperty(prop, str, dest); | |
379 } | |
380 } | |
381 | |
382 void Network::SetBooleanProperty(const char* prop, bool b, bool* dest) { | |
383 if (dest) | |
384 *dest = b; | |
385 SetValueProperty(prop, base::FundamentalValue(b)); | |
386 } | |
387 | |
388 void Network::SetIntegerProperty(const char* prop, int i, int* dest) { | |
389 if (dest) | |
390 *dest = i; | |
391 SetValueProperty(prop, base::FundamentalValue(i)); | |
392 } | |
393 | |
394 void Network::SetPreferred(bool preferred) { | |
395 if (preferred) { | |
396 SetIntegerProperty( | |
397 flimflam::kPriorityProperty, kPriorityPreferred, &priority_); | |
398 } else { | |
399 ClearProperty(flimflam::kPriorityProperty); | |
400 priority_ = kPriorityNotSet; | |
401 } | |
402 } | |
403 | |
404 void Network::SetAutoConnect(bool auto_connect) { | |
405 SetBooleanProperty( | |
406 flimflam::kAutoConnectProperty, auto_connect, &auto_connect_); | |
407 } | |
408 | |
409 void Network::SetSaveCredentials(bool save_credentials) { | |
410 SetBooleanProperty( | |
411 flimflam::kSaveCredentialsProperty, save_credentials, &save_credentials_); | |
412 } | |
413 | |
414 void Network::ClearUIData() { | |
415 ui_data_ = NetworkUIData(); | |
416 ClearProperty(flimflam::kUIDataProperty); | |
417 } | |
418 | |
419 void Network::AttemptConnection(const base::Closure& closure) { | |
420 // By default, just invoke the closure right away. Some subclasses | |
421 // (Wifi, VPN, etc.) override to do more work. | |
422 closure.Run(); | |
423 } | |
424 | |
425 void Network::set_connecting() { | |
426 state_ = STATE_CONNECT_REQUESTED; | |
427 } | |
428 | |
429 void Network::SetProfilePath(const std::string& profile_path) { | |
430 VLOG(1) << "Setting profile for: " << name_ << " to: " << profile_path; | |
431 SetOrClearStringProperty( | |
432 flimflam::kProfileProperty, profile_path, &profile_path_); | |
433 } | |
434 | |
435 std::string Network::GetStateString() const { | |
436 return ConnectionStateString(state_); | |
437 } | |
438 | |
439 std::string Network::GetErrorString() const { | |
440 switch (error_) { | |
441 case ERROR_NO_ERROR: | |
442 // TODO(nkostylev): Introduce new error message "None" instead. | |
443 return std::string(); | |
444 case ERROR_OUT_OF_RANGE: | |
445 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OUT_OF_RANGE); | |
446 case ERROR_PIN_MISSING: | |
447 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_PIN_MISSING); | |
448 case ERROR_DHCP_FAILED: | |
449 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_DHCP_FAILED); | |
450 case ERROR_CONNECT_FAILED: | |
451 return l10n_util::GetStringUTF8( | |
452 IDS_CHROMEOS_NETWORK_ERROR_CONNECT_FAILED); | |
453 case ERROR_BAD_PASSPHRASE: | |
454 return l10n_util::GetStringUTF8( | |
455 IDS_CHROMEOS_NETWORK_ERROR_BAD_PASSPHRASE); | |
456 case ERROR_BAD_WEPKEY: | |
457 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_BAD_WEPKEY); | |
458 case ERROR_ACTIVATION_FAILED: | |
459 return l10n_util::GetStringUTF8( | |
460 IDS_CHROMEOS_NETWORK_ERROR_ACTIVATION_FAILED); | |
461 case ERROR_NEED_EVDO: | |
462 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_NEED_EVDO); | |
463 case ERROR_NEED_HOME_NETWORK: | |
464 return l10n_util::GetStringUTF8( | |
465 IDS_CHROMEOS_NETWORK_ERROR_NEED_HOME_NETWORK); | |
466 case ERROR_OTASP_FAILED: | |
467 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_OTASP_FAILED); | |
468 case ERROR_AAA_FAILED: | |
469 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_AAA_FAILED); | |
470 case ERROR_INTERNAL: | |
471 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_INTERNAL); | |
472 case ERROR_DNS_LOOKUP_FAILED: | |
473 return l10n_util::GetStringUTF8( | |
474 IDS_CHROMEOS_NETWORK_ERROR_DNS_LOOKUP_FAILED); | |
475 case ERROR_HTTP_GET_FAILED: | |
476 return l10n_util::GetStringUTF8( | |
477 IDS_CHROMEOS_NETWORK_ERROR_HTTP_GET_FAILED); | |
478 case ERROR_IPSEC_PSK_AUTH_FAILED: | |
479 return l10n_util::GetStringUTF8( | |
480 IDS_CHROMEOS_NETWORK_ERROR_IPSEC_PSK_AUTH_FAILED); | |
481 case ERROR_IPSEC_CERT_AUTH_FAILED: | |
482 return l10n_util::GetStringUTF8( | |
483 IDS_CHROMEOS_NETWORK_ERROR_CERT_AUTH_FAILED); | |
484 case ERROR_PPP_AUTH_FAILED: | |
485 case ERROR_EAP_AUTHENTICATION_FAILED: | |
486 case ERROR_EAP_LOCAL_TLS_FAILED: | |
487 case ERROR_EAP_REMOTE_TLS_FAILED: | |
488 return l10n_util::GetStringUTF8( | |
489 IDS_CHROMEOS_NETWORK_ERROR_PPP_AUTH_FAILED); | |
490 case ERROR_UNKNOWN: | |
491 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); | |
492 } | |
493 return l10n_util::GetStringUTF8(IDS_CHROMEOS_NETWORK_STATE_UNRECOGNIZED); | |
494 } | |
495 | |
496 void Network::InitIPAddress() { | |
497 ip_address_.clear(); | |
498 if (!EnsureRunningOnChromeOS()) | |
499 return; | |
500 // If connected, get IPConfig. | |
501 if (connected() && !device_path_.empty()) { | |
502 CrosListIPConfigs(device_path_, | |
503 base::Bind(&Network::InitIPAddressCallback, | |
504 service_path_)); | |
505 } | |
506 } | |
507 | |
508 // static | |
509 void Network::InitIPAddressCallback( | |
510 const std::string& service_path, | |
511 const NetworkIPConfigVector& ip_configs, | |
512 const std::string& hardware_address) { | |
513 Network* network = | |
514 NetworkLibrary::Get()->FindNetworkByPath(service_path); | |
515 if (!network) | |
516 return; | |
517 for (size_t i = 0; i < ip_configs.size(); ++i) { | |
518 const NetworkIPConfig& ipconfig = ip_configs[i]; | |
519 if (ipconfig.address.size() > 0) { | |
520 network->ip_address_ = ipconfig.address; | |
521 break; | |
522 } | |
523 } | |
524 } | |
525 | |
526 bool Network::UpdateStatus(const std::string& key, | |
527 const Value& value, | |
528 PropertyIndex* index) { | |
529 if (network_parser_.get()) | |
530 return network_parser_->UpdateStatus(key, value, this, index); | |
531 return false; | |
532 } | |
533 | |
534 //////////////////////////////////////////////////////////////////////////////// | |
535 // EthernetNetwork | |
536 | |
537 EthernetNetwork::EthernetNetwork(const std::string& service_path) | |
538 : Network(service_path, TYPE_ETHERNET) { | |
539 } | |
540 | |
541 //////////////////////////////////////////////////////////////////////////////// | |
542 // VirtualNetwork | |
543 | |
544 VirtualNetwork::VirtualNetwork(const std::string& service_path) | |
545 : Network(service_path, TYPE_VPN), | |
546 provider_type_(PROVIDER_TYPE_L2TP_IPSEC_PSK), | |
547 // Assume PSK and user passphrase are not available initially | |
548 psk_passphrase_required_(true), | |
549 user_passphrase_required_(true), | |
550 weak_pointer_factory_(this) { | |
551 } | |
552 | |
553 VirtualNetwork::~VirtualNetwork() {} | |
554 | |
555 void VirtualNetwork::EraseCredentials() { | |
556 WipeString(&ca_cert_pem_); | |
557 WipeString(&psk_passphrase_); | |
558 WipeString(&client_cert_id_); | |
559 WipeString(&user_passphrase_); | |
560 } | |
561 | |
562 void VirtualNetwork::CalculateUniqueId() { | |
563 std::string provider_type(ProviderTypeToString(provider_type_)); | |
564 set_unique_id(provider_type + "|" + server_hostname_); | |
565 } | |
566 | |
567 bool VirtualNetwork::RequiresUserProfile() const { | |
568 return true; | |
569 } | |
570 | |
571 void VirtualNetwork::AttemptConnection(const base::Closure& connect) { | |
572 if (client_cert_type() == CLIENT_CERT_TYPE_PATTERN) { | |
573 MatchCertificatePattern(true, connect); | |
574 } else { | |
575 connect.Run(); | |
576 } | |
577 } | |
578 | |
579 void VirtualNetwork::CopyCredentialsFromRemembered(Network* remembered) { | |
580 CHECK_EQ(remembered->type(), TYPE_VPN); | |
581 VirtualNetwork* remembered_vpn = static_cast<VirtualNetwork*>(remembered); | |
582 VLOG(1) << "Copy VPN credentials: " << name() | |
583 << " username: " << remembered_vpn->username(); | |
584 if (ca_cert_pem_.empty()) | |
585 ca_cert_pem_ = remembered_vpn->ca_cert_pem(); | |
586 if (psk_passphrase_.empty()) | |
587 psk_passphrase_ = remembered_vpn->psk_passphrase(); | |
588 if (client_cert_id_.empty()) | |
589 client_cert_id_ = remembered_vpn->client_cert_id(); | |
590 if (username_.empty()) | |
591 username_ = remembered_vpn->username(); | |
592 if (user_passphrase_.empty()) | |
593 user_passphrase_ = remembered_vpn->user_passphrase(); | |
594 } | |
595 | |
596 bool VirtualNetwork::NeedMoreInfoToConnect() const { | |
597 if (server_hostname_.empty()) { | |
598 VLOG(1) << "server_hostname_.empty()"; | |
599 return true; | |
600 } | |
601 if (username_.empty()) { | |
602 VLOG(1) << "username_.empty()"; | |
603 return true; | |
604 } | |
605 if (IsUserPassphraseRequired()) { | |
606 VLOG(1) << "User Passphrase Required"; | |
607 return true; | |
608 } | |
609 if (error() != ERROR_NO_ERROR) { | |
610 VLOG(1) << "Error: " << error(); | |
611 return true; | |
612 } | |
613 switch (provider_type_) { | |
614 case PROVIDER_TYPE_L2TP_IPSEC_PSK: | |
615 if (IsPSKPassphraseRequired()) { | |
616 VLOG(1) << "PSK Passphrase Required"; | |
617 return true; | |
618 } | |
619 break; | |
620 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: | |
621 if (client_cert_id_.empty() && | |
622 client_cert_type() != CLIENT_CERT_TYPE_PATTERN) { | |
623 VLOG(1) << "Certificate Required"; | |
624 return true; | |
625 } | |
626 break; | |
627 case PROVIDER_TYPE_OPEN_VPN: | |
628 if (client_cert_id_.empty()) { | |
629 VLOG(1) << "client_cert_id_.empty()"; | |
630 return true; | |
631 } | |
632 // For now we always need additional info for OpenVPN. | |
633 // TODO(stevenjb): Check connectable() once shill sets that state | |
634 // properly, or define another mechanism to determine when additional | |
635 // credentials are required. | |
636 VLOG(1) << "OpenVPN requires credentials, connectable: " | |
637 << connectable(); | |
638 return true; | |
639 break; | |
640 case PROVIDER_TYPE_MAX: | |
641 NOTREACHED(); | |
642 break; | |
643 } | |
644 return false; | |
645 } | |
646 | |
647 std::string VirtualNetwork::GetProviderTypeString() const { | |
648 switch (provider_type_) { | |
649 case PROVIDER_TYPE_L2TP_IPSEC_PSK: | |
650 return l10n_util::GetStringUTF8( | |
651 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK); | |
652 break; | |
653 case PROVIDER_TYPE_L2TP_IPSEC_USER_CERT: | |
654 return l10n_util::GetStringUTF8( | |
655 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT); | |
656 break; | |
657 case PROVIDER_TYPE_OPEN_VPN: | |
658 return l10n_util::GetStringUTF8( | |
659 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN); | |
660 break; | |
661 default: | |
662 return l10n_util::GetStringUTF8( | |
663 IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); | |
664 break; | |
665 } | |
666 } | |
667 | |
668 bool VirtualNetwork::IsPSKPassphraseRequired() const { | |
669 return psk_passphrase_required_ && psk_passphrase_.empty(); | |
670 } | |
671 | |
672 bool VirtualNetwork::IsUserPassphraseRequired() const { | |
673 return user_passphrase_required_ && user_passphrase_.empty(); | |
674 } | |
675 | |
676 void VirtualNetwork::SetCACertPEM(const std::string& ca_cert_pem) { | |
677 VLOG(1) << "SetCACertPEM " << ca_cert_pem; | |
678 if (provider_type_ == PROVIDER_TYPE_OPEN_VPN) { | |
679 ca_cert_pem_ = ca_cert_pem; | |
680 base::ListValue pem_list; | |
681 pem_list.AppendString(ca_cert_pem_); | |
682 SetValueProperty(shill::kOpenVPNCaCertPemProperty, pem_list); | |
683 } else { | |
684 SetStringProperty( | |
685 shill::kL2tpIpsecCaCertPemProperty, ca_cert_pem, &ca_cert_pem_); | |
686 } | |
687 } | |
688 | |
689 void VirtualNetwork::SetL2TPIPsecPSKCredentials( | |
690 const std::string& psk_passphrase, | |
691 const std::string& username, | |
692 const std::string& user_passphrase, | |
693 const std::string& group_name) { | |
694 if (!psk_passphrase.empty()) { | |
695 SetStringProperty(flimflam::kL2tpIpsecPskProperty, | |
696 psk_passphrase, &psk_passphrase_); | |
697 } | |
698 SetStringProperty(flimflam::kL2tpIpsecUserProperty, username, &username_); | |
699 if (!user_passphrase.empty()) { | |
700 SetStringProperty(flimflam::kL2tpIpsecPasswordProperty, | |
701 user_passphrase, &user_passphrase_); | |
702 } | |
703 SetStringProperty(shill::kL2tpIpsecTunnelGroupProperty, | |
704 group_name, &group_name_); | |
705 } | |
706 | |
707 void VirtualNetwork::SetL2TPIPsecCertCredentials( | |
708 const std::string& client_cert_id, | |
709 const std::string& username, | |
710 const std::string& user_passphrase, | |
711 const std::string& group_name) { | |
712 SetStringProperty(flimflam::kL2tpIpsecClientCertIdProperty, | |
713 client_cert_id, &client_cert_id_); | |
714 SetStringProperty(flimflam::kL2tpIpsecUserProperty, username, &username_); | |
715 if (!user_passphrase.empty()) { | |
716 SetStringProperty(flimflam::kL2tpIpsecPasswordProperty, | |
717 user_passphrase, &user_passphrase_); | |
718 } | |
719 SetStringProperty(shill::kL2tpIpsecTunnelGroupProperty, | |
720 group_name, &group_name_); | |
721 } | |
722 | |
723 void VirtualNetwork::SetOpenVPNCredentials( | |
724 const std::string& client_cert_id, | |
725 const std::string& username, | |
726 const std::string& user_passphrase, | |
727 const std::string& otp) { | |
728 SetStringProperty(flimflam::kOpenVPNClientCertIdProperty, | |
729 client_cert_id, &client_cert_id_); | |
730 SetStringProperty(flimflam::kOpenVPNUserProperty, username, &username_); | |
731 if (!user_passphrase.empty()) { | |
732 SetStringProperty(flimflam::kOpenVPNPasswordProperty, | |
733 user_passphrase, &user_passphrase_); | |
734 } | |
735 SetStringProperty(flimflam::kOpenVPNOTPProperty, otp, NULL); | |
736 } | |
737 | |
738 void VirtualNetwork::SetServerHostname(const std::string& server_hostname) { | |
739 SetStringProperty(flimflam::kProviderHostProperty, | |
740 server_hostname, &server_hostname_); | |
741 } | |
742 | |
743 void VirtualNetwork::SetCertificateSlotAndPin( | |
744 const std::string& slot, const std::string& pin) { | |
745 if (provider_type() == PROVIDER_TYPE_OPEN_VPN) { | |
746 SetOrClearStringProperty(flimflam::kOpenVPNClientCertSlotProperty, | |
747 slot, NULL); | |
748 SetOrClearStringProperty(flimflam::kOpenVPNPinProperty, pin, NULL); | |
749 } else { | |
750 SetOrClearStringProperty(flimflam::kL2tpIpsecClientCertSlotProperty, | |
751 slot, NULL); | |
752 SetOrClearStringProperty(flimflam::kL2tpIpsecPinProperty, pin, NULL); | |
753 } | |
754 } | |
755 | |
756 void VirtualNetwork::MatchCertificatePattern(bool allow_enroll, | |
757 const base::Closure& connect) { | |
758 DCHECK(client_cert_type() == CLIENT_CERT_TYPE_PATTERN); | |
759 DCHECK(!client_cert_pattern().Empty()); | |
760 | |
761 // We skip certificate patterns for device policy ONC so that an unmanaged | |
762 // user can't get to the place where a cert is presented for them | |
763 // involuntarily. | |
764 if (client_cert_pattern().Empty() || | |
765 ui_data().onc_source() == onc::ONC_SOURCE_DEVICE_POLICY) { | |
766 connect.Run(); | |
767 return; | |
768 } | |
769 | |
770 scoped_refptr<net::X509Certificate> matching_cert = | |
771 client_cert::GetCertificateMatch(client_cert_pattern()); | |
772 if (matching_cert.get()) { | |
773 std::string client_cert_id = | |
774 x509_certificate_model::GetPkcs11Id(matching_cert->os_cert_handle()); | |
775 if (provider_type() == PROVIDER_TYPE_OPEN_VPN) { | |
776 SetStringProperty(flimflam::kOpenVPNClientCertIdProperty, | |
777 client_cert_id, &client_cert_id_); | |
778 } else { | |
779 SetStringProperty(flimflam::kL2tpIpsecClientCertIdProperty, | |
780 client_cert_id, &client_cert_id_); | |
781 } | |
782 } else { | |
783 if (allow_enroll && enrollment_delegate()) { | |
784 // Wrap the closure in another callback so that we can retry the | |
785 // certificate match again before actually connecting. | |
786 base::Closure wrapped_connect = | |
787 base::Bind(&VirtualNetwork::MatchCertificatePattern, | |
788 weak_pointer_factory_.GetWeakPtr(), | |
789 false, | |
790 connect); | |
791 | |
792 enrollment_delegate()->Enroll(client_cert_pattern().enrollment_uri_list(), | |
793 wrapped_connect); | |
794 // Enrollment delegate will take care of running the closure at the | |
795 // appropriate time, if the user doesn't cancel. | |
796 return; | |
797 } | |
798 } | |
799 connect.Run(); | |
800 } | |
801 | |
802 //////////////////////////////////////////////////////////////////////////////// | |
803 // WirelessNetwork | |
804 | |
805 //////////////////////////////////////////////////////////////////////////////// | |
806 // CellTower | |
807 | |
808 CellTower::CellTower() {} | |
809 | |
810 //////////////////////////////////////////////////////////////////////////////// | |
811 // CellularApn | |
812 | |
813 CellularApn::CellularApn() {} | |
814 | |
815 CellularApn::CellularApn( | |
816 const std::string& apn, const std::string& network_id, | |
817 const std::string& username, const std::string& password) | |
818 : apn(apn), network_id(network_id), | |
819 username(username), password(password) { | |
820 } | |
821 | |
822 CellularApn::~CellularApn() {} | |
823 | |
824 void CellularApn::Set(const DictionaryValue& dict) { | |
825 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnProperty, &apn)) | |
826 apn.clear(); | |
827 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnNetworkIdProperty, | |
828 &network_id)) | |
829 network_id.clear(); | |
830 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnUsernameProperty, | |
831 &username)) | |
832 username.clear(); | |
833 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnPasswordProperty, | |
834 &password)) | |
835 password.clear(); | |
836 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnNameProperty, &name)) | |
837 name.clear(); | |
838 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnLocalizedNameProperty, | |
839 &localized_name)) | |
840 localized_name.clear(); | |
841 if (!dict.GetStringWithoutPathExpansion(flimflam::kApnLanguageProperty, | |
842 &language)) | |
843 language.clear(); | |
844 } | |
845 | |
846 //////////////////////////////////////////////////////////////////////////////// | |
847 // CellularNetwork | |
848 | |
849 CellularNetwork::CellularNetwork(const std::string& service_path) | |
850 : WirelessNetwork(service_path, TYPE_CELLULAR), | |
851 activate_over_non_cellular_network_(false), | |
852 out_of_credits_(false), | |
853 activation_state_(ACTIVATION_STATE_UNKNOWN), | |
854 network_technology_(NETWORK_TECHNOLOGY_UNKNOWN), | |
855 roaming_state_(ROAMING_STATE_UNKNOWN), | |
856 using_post_(false) { | |
857 } | |
858 | |
859 CellularNetwork::~CellularNetwork() { | |
860 } | |
861 | |
862 bool CellularNetwork::StartActivation() { | |
863 if (!EnsureRunningOnChromeOS()) | |
864 return false; | |
865 if (!CrosActivateCellularModem(service_path(), "")) | |
866 return false; | |
867 // Don't wait for shill to tell us that we are really activating since | |
868 // other notifications in the message loop might cause us to think that | |
869 // the process hasn't started yet. | |
870 activation_state_ = ACTIVATION_STATE_ACTIVATING; | |
871 return true; | |
872 } | |
873 | |
874 void CellularNetwork::CompleteActivation() { | |
875 if (!EnsureRunningOnChromeOS()) | |
876 return; | |
877 CrosCompleteCellularActivation(service_path()); | |
878 } | |
879 | |
880 void CellularNetwork::SetApn(const CellularApn& apn) { | |
881 if (!apn.apn.empty()) { | |
882 DictionaryValue value; | |
883 // Only use the fields that are needed for establishing | |
884 // connections, and ignore the rest. | |
885 value.SetString(flimflam::kApnProperty, apn.apn); | |
886 value.SetString(flimflam::kApnNetworkIdProperty, apn.network_id); | |
887 value.SetString(flimflam::kApnUsernameProperty, apn.username); | |
888 value.SetString(flimflam::kApnPasswordProperty, apn.password); | |
889 SetValueProperty(flimflam::kCellularApnProperty, value); | |
890 } else { | |
891 ClearProperty(flimflam::kCellularApnProperty); | |
892 } | |
893 } | |
894 | |
895 bool CellularNetwork::SupportsActivation() const { | |
896 return !usage_url().empty() || !payment_url().empty(); | |
897 } | |
898 | |
899 bool CellularNetwork::NeedsActivation() const { | |
900 return (activation_state() == ACTIVATION_STATE_NOT_ACTIVATED || | |
901 activation_state() == ACTIVATION_STATE_PARTIALLY_ACTIVATED); | |
902 } | |
903 | |
904 std::string CellularNetwork::GetNetworkTechnologyString() const { | |
905 // No need to localize these cellular technology abbreviations. | |
906 switch (network_technology_) { | |
907 case NETWORK_TECHNOLOGY_1XRTT: | |
908 return "1xRTT"; | |
909 break; | |
910 case NETWORK_TECHNOLOGY_EVDO: | |
911 return "EVDO"; | |
912 break; | |
913 case NETWORK_TECHNOLOGY_GPRS: | |
914 return "GPRS"; | |
915 break; | |
916 case NETWORK_TECHNOLOGY_EDGE: | |
917 return "EDGE"; | |
918 break; | |
919 case NETWORK_TECHNOLOGY_UMTS: | |
920 return "UMTS"; | |
921 break; | |
922 case NETWORK_TECHNOLOGY_HSPA: | |
923 return "HSPA"; | |
924 break; | |
925 case NETWORK_TECHNOLOGY_HSPA_PLUS: | |
926 return "HSPA Plus"; | |
927 break; | |
928 case NETWORK_TECHNOLOGY_LTE: | |
929 return "LTE"; | |
930 break; | |
931 case NETWORK_TECHNOLOGY_LTE_ADVANCED: | |
932 return "LTE Advanced"; | |
933 break; | |
934 case NETWORK_TECHNOLOGY_GSM: | |
935 return "GSM"; | |
936 break; | |
937 default: | |
938 return l10n_util::GetStringUTF8( | |
939 IDS_CHROMEOS_NETWORK_CELLULAR_TECHNOLOGY_UNKNOWN); | |
940 break; | |
941 } | |
942 } | |
943 | |
944 std::string CellularNetwork::ActivationStateToString( | |
945 ActivationState activation_state) { | |
946 switch (activation_state) { | |
947 case ACTIVATION_STATE_ACTIVATED: | |
948 return l10n_util::GetStringUTF8( | |
949 IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATED); | |
950 break; | |
951 case ACTIVATION_STATE_ACTIVATING: | |
952 return l10n_util::GetStringUTF8( | |
953 IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_ACTIVATING); | |
954 break; | |
955 case ACTIVATION_STATE_NOT_ACTIVATED: | |
956 return l10n_util::GetStringUTF8( | |
957 IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_NOT_ACTIVATED); | |
958 break; | |
959 case ACTIVATION_STATE_PARTIALLY_ACTIVATED: | |
960 return l10n_util::GetStringUTF8( | |
961 IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_PARTIALLY_ACTIVATED); | |
962 break; | |
963 default: | |
964 return l10n_util::GetStringUTF8( | |
965 IDS_CHROMEOS_NETWORK_ACTIVATION_STATE_UNKNOWN); | |
966 break; | |
967 } | |
968 } | |
969 | |
970 std::string CellularNetwork::GetActivationStateString() const { | |
971 return ActivationStateToString(this->activation_state_); | |
972 } | |
973 | |
974 std::string CellularNetwork::GetRoamingStateString() const { | |
975 switch (this->roaming_state_) { | |
976 case ROAMING_STATE_HOME: | |
977 return l10n_util::GetStringUTF8( | |
978 IDS_CHROMEOS_NETWORK_ROAMING_STATE_HOME); | |
979 break; | |
980 case ROAMING_STATE_ROAMING: | |
981 return l10n_util::GetStringUTF8( | |
982 IDS_CHROMEOS_NETWORK_ROAMING_STATE_ROAMING); | |
983 break; | |
984 default: | |
985 return l10n_util::GetStringUTF8( | |
986 IDS_CHROMEOS_NETWORK_ROAMING_STATE_UNKNOWN); | |
987 break; | |
988 } | |
989 } | |
990 | |
991 //////////////////////////////////////////////////////////////////////////////// | |
992 // WifiNetwork | |
993 | |
994 WifiNetwork::WifiNetwork(const std::string& service_path) | |
995 : WirelessNetwork(service_path, TYPE_WIFI), | |
996 encryption_(SECURITY_NONE), | |
997 passphrase_required_(false), | |
998 hidden_ssid_(false), | |
999 frequency_(0), | |
1000 eap_method_(EAP_METHOD_UNKNOWN), | |
1001 eap_phase_2_auth_(EAP_PHASE_2_AUTH_AUTO), | |
1002 eap_use_system_cas_(true), | |
1003 eap_save_credentials_(false), | |
1004 weak_pointer_factory_(this) { | |
1005 } | |
1006 | |
1007 WifiNetwork::~WifiNetwork() {} | |
1008 | |
1009 void WifiNetwork::CalculateUniqueId() { | |
1010 ConnectionSecurity encryption = encryption_; | |
1011 // Shill treats wpa and rsn as psk internally, so convert those types | |
1012 // to psk for unique naming. | |
1013 if (encryption == SECURITY_WPA || encryption == SECURITY_RSN) | |
1014 encryption = SECURITY_PSK; | |
1015 std::string security = std::string(SecurityToString(encryption)); | |
1016 set_unique_id(security + "|" + name()); | |
1017 } | |
1018 | |
1019 bool WifiNetwork::SetSsid(const std::string& ssid) { | |
1020 // Detects encoding and convert to UTF-8. | |
1021 std::string ssid_utf8; | |
1022 if (!IsStringUTF8(ssid)) { | |
1023 std::string encoding; | |
1024 if (base::DetectEncoding(ssid, &encoding)) { | |
1025 if (!base::ConvertToUtf8AndNormalize(ssid, encoding, &ssid_utf8)) { | |
1026 ssid_utf8.clear(); | |
1027 } | |
1028 } | |
1029 } | |
1030 | |
1031 if (ssid_utf8.empty()) | |
1032 SetName(ssid); | |
1033 else | |
1034 SetName(ssid_utf8); | |
1035 | |
1036 return true; | |
1037 } | |
1038 | |
1039 bool WifiNetwork::SetHexSsid(const std::string& ssid_hex) { | |
1040 // Converts ascii hex dump (eg. "49656c6c6f") to string (eg. "Hello"). | |
1041 std::vector<uint8> ssid_raw; | |
1042 if (!base::HexStringToBytes(ssid_hex, &ssid_raw)) { | |
1043 LOG(ERROR) << "Illegal hex char is found in WiFi.HexSSID."; | |
1044 ssid_raw.clear(); | |
1045 return false; | |
1046 } | |
1047 | |
1048 return SetSsid(std::string(ssid_raw.begin(), ssid_raw.end())); | |
1049 } | |
1050 | |
1051 const std::string& WifiNetwork::GetPassphrase() const { | |
1052 if (!user_passphrase_.empty()) | |
1053 return user_passphrase_; | |
1054 return passphrase_; | |
1055 } | |
1056 | |
1057 void WifiNetwork::SetPassphrase(const std::string& passphrase) { | |
1058 // Set the user_passphrase_ only; passphrase_ stores the shill value. | |
1059 // If the user sets an empty passphrase, restore it to the passphrase | |
1060 // remembered by shill. | |
1061 if (!passphrase.empty()) { | |
1062 user_passphrase_ = passphrase; | |
1063 passphrase_ = passphrase; | |
1064 } else { | |
1065 user_passphrase_ = passphrase_; | |
1066 } | |
1067 // Send the change to shill. If the format is valid, it will propagate to | |
1068 // passphrase_ with a service update. | |
1069 SetOrClearStringProperty(flimflam::kPassphraseProperty, passphrase, NULL); | |
1070 } | |
1071 | |
1072 // See src/third_party/shill/doc/service-api.txt for properties that | |
1073 // shill will forget when SaveCredentials is false. | |
1074 void WifiNetwork::EraseCredentials() { | |
1075 WipeString(&passphrase_); | |
1076 WipeString(&user_passphrase_); | |
1077 WipeString(&eap_server_ca_cert_pem_); | |
1078 WipeString(&eap_client_cert_pkcs11_id_); | |
1079 WipeString(&eap_identity_); | |
1080 WipeString(&eap_anonymous_identity_); | |
1081 WipeString(&eap_passphrase_); | |
1082 } | |
1083 | |
1084 void WifiNetwork::SetEAPMethod(EAPMethod method) { | |
1085 eap_method_ = method; | |
1086 switch (method) { | |
1087 case EAP_METHOD_PEAP: | |
1088 SetStringProperty( | |
1089 flimflam::kEapMethodProperty, flimflam::kEapMethodPEAP, NULL); | |
1090 break; | |
1091 case EAP_METHOD_TLS: | |
1092 SetStringProperty( | |
1093 flimflam::kEapMethodProperty, flimflam::kEapMethodTLS, NULL); | |
1094 break; | |
1095 case EAP_METHOD_TTLS: | |
1096 SetStringProperty( | |
1097 flimflam::kEapMethodProperty, flimflam::kEapMethodTTLS, NULL); | |
1098 break; | |
1099 case EAP_METHOD_LEAP: | |
1100 SetStringProperty( | |
1101 flimflam::kEapMethodProperty, flimflam::kEapMethodLEAP, NULL); | |
1102 break; | |
1103 default: | |
1104 ClearProperty(flimflam::kEapMethodProperty); | |
1105 break; | |
1106 } | |
1107 } | |
1108 | |
1109 void WifiNetwork::SetEAPPhase2Auth(EAPPhase2Auth auth) { | |
1110 eap_phase_2_auth_ = auth; | |
1111 bool is_peap = (eap_method_ == EAP_METHOD_PEAP); | |
1112 switch (auth) { | |
1113 case EAP_PHASE_2_AUTH_AUTO: | |
1114 ClearProperty(flimflam::kEapPhase2AuthProperty); | |
1115 break; | |
1116 case EAP_PHASE_2_AUTH_MD5: | |
1117 SetStringProperty(flimflam::kEapPhase2AuthProperty, | |
1118 is_peap ? flimflam::kEapPhase2AuthPEAPMD5 | |
1119 : flimflam::kEapPhase2AuthTTLSMD5, | |
1120 NULL); | |
1121 break; | |
1122 case EAP_PHASE_2_AUTH_MSCHAPV2: | |
1123 SetStringProperty(flimflam::kEapPhase2AuthProperty, | |
1124 is_peap ? flimflam::kEapPhase2AuthPEAPMSCHAPV2 | |
1125 : flimflam::kEapPhase2AuthTTLSMSCHAPV2, | |
1126 NULL); | |
1127 break; | |
1128 case EAP_PHASE_2_AUTH_MSCHAP: | |
1129 SetStringProperty(flimflam::kEapPhase2AuthProperty, | |
1130 flimflam::kEapPhase2AuthTTLSMSCHAP, NULL); | |
1131 break; | |
1132 case EAP_PHASE_2_AUTH_PAP: | |
1133 SetStringProperty(flimflam::kEapPhase2AuthProperty, | |
1134 flimflam::kEapPhase2AuthTTLSPAP, NULL); | |
1135 break; | |
1136 case EAP_PHASE_2_AUTH_CHAP: | |
1137 SetStringProperty(flimflam::kEapPhase2AuthProperty, | |
1138 flimflam::kEapPhase2AuthTTLSCHAP, NULL); | |
1139 break; | |
1140 } | |
1141 } | |
1142 | |
1143 void WifiNetwork::SetEAPServerCaCertPEM( | |
1144 const std::string& ca_cert_pem) { | |
1145 VLOG(1) << "SetEAPServerCaCertPEM " << ca_cert_pem; | |
1146 eap_server_ca_cert_pem_ = ca_cert_pem; | |
1147 base::ListValue pem_list; | |
1148 pem_list.AppendString(ca_cert_pem); | |
1149 SetValueProperty(shill::kEapCaCertPemProperty, pem_list); | |
1150 } | |
1151 | |
1152 void WifiNetwork::SetEAPClientCertPkcs11Id(const std::string& pkcs11_id) { | |
1153 VLOG(1) << "SetEAPClientCertPkcs11Id " << pkcs11_id; | |
1154 SetOrClearStringProperty( | |
1155 flimflam::kEapCertIdProperty, pkcs11_id, &eap_client_cert_pkcs11_id_); | |
1156 // shill requires both CertID and KeyID for TLS connections, despite | |
1157 // the fact that by convention they are the same ID. | |
1158 SetOrClearStringProperty(flimflam::kEapKeyIdProperty, pkcs11_id, NULL); | |
1159 } | |
1160 | |
1161 void WifiNetwork::SetEAPUseSystemCAs(bool use_system_cas) { | |
1162 SetBooleanProperty(flimflam::kEapUseSystemCasProperty, use_system_cas, | |
1163 &eap_use_system_cas_); | |
1164 } | |
1165 | |
1166 void WifiNetwork::SetEAPIdentity(const std::string& identity) { | |
1167 SetOrClearStringProperty( | |
1168 flimflam::kEapIdentityProperty, identity, &eap_identity_); | |
1169 } | |
1170 | |
1171 void WifiNetwork::SetEAPAnonymousIdentity(const std::string& identity) { | |
1172 SetOrClearStringProperty(flimflam::kEapAnonymousIdentityProperty, identity, | |
1173 &eap_anonymous_identity_); | |
1174 } | |
1175 | |
1176 void WifiNetwork::SetEAPPassphrase(const std::string& passphrase) { | |
1177 SetOrClearStringProperty( | |
1178 flimflam::kEapPasswordProperty, passphrase, &eap_passphrase_); | |
1179 } | |
1180 | |
1181 std::string WifiNetwork::GetEncryptionString() const { | |
1182 switch (encryption_) { | |
1183 case SECURITY_UNKNOWN: | |
1184 break; | |
1185 case SECURITY_NONE: | |
1186 return ""; | |
1187 case SECURITY_WEP: | |
1188 return "WEP"; | |
1189 case SECURITY_WPA: | |
1190 return "WPA"; | |
1191 case SECURITY_RSN: | |
1192 return "RSN"; | |
1193 case SECURITY_8021X: { | |
1194 std::string result("8021X"); | |
1195 switch (eap_method_) { | |
1196 case EAP_METHOD_PEAP: | |
1197 result += "+PEAP"; | |
1198 break; | |
1199 case EAP_METHOD_TLS: | |
1200 result += "+TLS"; | |
1201 break; | |
1202 case EAP_METHOD_TTLS: | |
1203 result += "+TTLS"; | |
1204 break; | |
1205 case EAP_METHOD_LEAP: | |
1206 result += "+LEAP"; | |
1207 break; | |
1208 default: | |
1209 break; | |
1210 } | |
1211 return result; | |
1212 } | |
1213 case SECURITY_PSK: | |
1214 return "PSK"; | |
1215 } | |
1216 return "Unknown"; | |
1217 } | |
1218 | |
1219 bool WifiNetwork::IsPassphraseRequired() const { | |
1220 if (encryption_ == SECURITY_NONE) | |
1221 return false; | |
1222 // A connection failure might be due to a bad passphrase. | |
1223 if (error() == ERROR_BAD_PASSPHRASE || | |
1224 error() == ERROR_BAD_WEPKEY || | |
1225 error() == ERROR_PPP_AUTH_FAILED || | |
1226 error() == ERROR_EAP_LOCAL_TLS_FAILED || | |
1227 error() == ERROR_EAP_REMOTE_TLS_FAILED || | |
1228 error() == ERROR_EAP_AUTHENTICATION_FAILED || | |
1229 error() == ERROR_CONNECT_FAILED || | |
1230 error() == ERROR_UNKNOWN) { | |
1231 VLOG(1) << "Authentication Error: " << GetErrorString(); | |
1232 return true; | |
1233 } | |
1234 // If the user initiated a connection and it failed, request credentials in | |
1235 // case it is a credentials error and Shill was unable to detect it. | |
1236 if (user_connect_state() == USER_CONNECT_FAILED) | |
1237 return true; | |
1238 // WEP/WPA/RSN and PSK networks rely on the PassphraseRequired property. | |
1239 if (encryption_ != SECURITY_8021X) | |
1240 return passphrase_required_; | |
1241 // For 802.1x networks, if we are using a certificate pattern we do not | |
1242 // need any credentials. | |
1243 if (eap_method_ == EAP_METHOD_TLS && | |
1244 client_cert_type() == CLIENT_CERT_TYPE_PATTERN) { | |
1245 return false; | |
1246 } | |
1247 // Connectable will be false if 802.1x credentials are not set | |
1248 return !connectable(); | |
1249 } | |
1250 | |
1251 bool WifiNetwork::RequiresUserProfile() const { | |
1252 // 8021X requires certificates which are only stored for individual users. | |
1253 if (encryption_ != SECURITY_8021X) | |
1254 return false; | |
1255 | |
1256 if (eap_method_ != EAP_METHOD_TLS) | |
1257 return false; | |
1258 | |
1259 if (eap_client_cert_pkcs11_id().empty() && | |
1260 client_cert_type() != CLIENT_CERT_TYPE_PATTERN) | |
1261 return false; | |
1262 | |
1263 return true; | |
1264 } | |
1265 | |
1266 void WifiNetwork::AttemptConnection(const base::Closure& connect) { | |
1267 if (client_cert_type() == CLIENT_CERT_TYPE_PATTERN) { | |
1268 MatchCertificatePattern(true, connect); | |
1269 } else { | |
1270 connect.Run(); | |
1271 } | |
1272 } | |
1273 | |
1274 void WifiNetwork::SetCertificatePin(const std::string& pin) { | |
1275 SetOrClearStringProperty(flimflam::kEapPinProperty, pin, NULL); | |
1276 } | |
1277 | |
1278 void WifiNetwork::MatchCertificatePattern(bool allow_enroll, | |
1279 const base::Closure& connect) { | |
1280 DCHECK(client_cert_type() == CLIENT_CERT_TYPE_PATTERN); | |
1281 DCHECK(!client_cert_pattern().Empty()); | |
1282 if (client_cert_pattern().Empty()) { | |
1283 connect.Run(); | |
1284 return; | |
1285 } | |
1286 | |
1287 scoped_refptr<net::X509Certificate> matching_cert = | |
1288 client_cert::GetCertificateMatch(client_cert_pattern()); | |
1289 if (matching_cert.get()) { | |
1290 SetEAPClientCertPkcs11Id( | |
1291 x509_certificate_model::GetPkcs11Id(matching_cert->os_cert_handle())); | |
1292 } else { | |
1293 if (allow_enroll && enrollment_delegate()) { | |
1294 // Wrap the closure in another callback so that we can retry the | |
1295 // certificate match again before actually connecting. | |
1296 base::Closure wrapped_connect = | |
1297 base::Bind(&WifiNetwork::MatchCertificatePattern, | |
1298 weak_pointer_factory_.GetWeakPtr(), | |
1299 false, | |
1300 connect); | |
1301 | |
1302 enrollment_delegate()->Enroll(client_cert_pattern().enrollment_uri_list(), | |
1303 wrapped_connect); | |
1304 // Enrollment delegate should take care of running the closure at the | |
1305 // appropriate time, if the user doesn't cancel. | |
1306 return; | |
1307 } | |
1308 } | |
1309 connect.Run(); | |
1310 } | |
1311 | |
1312 //////////////////////////////////////////////////////////////////////////////// | |
1313 // WimaxNetwork | |
1314 | |
1315 WimaxNetwork::WimaxNetwork(const std::string& service_path) | |
1316 : WirelessNetwork(service_path, TYPE_WIMAX), | |
1317 passphrase_required_(false) { | |
1318 } | |
1319 | |
1320 WimaxNetwork::~WimaxNetwork() { | |
1321 } | |
1322 | |
1323 void WimaxNetwork::EraseCredentials() { | |
1324 WipeString(&eap_passphrase_); | |
1325 WipeString(&eap_identity_); | |
1326 } | |
1327 | |
1328 void WimaxNetwork::SetEAPPassphrase(const std::string& passphrase) { | |
1329 SetOrClearStringProperty( | |
1330 flimflam::kEapPasswordProperty, passphrase, &eap_passphrase_); | |
1331 } | |
1332 | |
1333 void WimaxNetwork::SetEAPIdentity(const std::string& identity) { | |
1334 SetOrClearStringProperty( | |
1335 flimflam::kEapIdentityProperty, identity, &eap_identity_); | |
1336 } | |
1337 | |
1338 void WimaxNetwork::CalculateUniqueId() { | |
1339 set_unique_id(name() + "|" + eap_identity()); | |
1340 } | |
1341 | |
1342 NetworkLibrary::EAPConfigData::EAPConfigData() | |
1343 : method(EAP_METHOD_UNKNOWN), | |
1344 auth(EAP_PHASE_2_AUTH_AUTO), | |
1345 use_system_cas(true) { | |
1346 } | |
1347 | |
1348 NetworkLibrary::EAPConfigData::~EAPConfigData() {} | |
1349 | |
1350 NetworkLibrary::VPNConfigData::VPNConfigData() | |
1351 : save_credentials(false) { | |
1352 } | |
1353 | |
1354 NetworkLibrary::VPNConfigData::~VPNConfigData() {} | |
1355 | |
1356 // static | |
1357 NetworkLibrary* NetworkLibrary::GetImpl(bool stub) { | |
1358 NetworkLibrary* impl; | |
1359 if (stub) | |
1360 impl = new NetworkLibraryImplStub(); | |
1361 else | |
1362 impl = new NetworkLibraryImplCros(); | |
1363 impl->Init(); | |
1364 return impl; | |
1365 } | |
1366 | |
1367 // static | |
1368 void NetworkLibrary::Initialize(bool use_stub) { | |
1369 CHECK(!g_network_library) | |
1370 << "NetworkLibrary: Multiple calls to Initialize()."; | |
1371 g_network_library = NetworkLibrary::GetImpl(use_stub); | |
1372 VLOG_IF(1, use_stub) << "NetworkLibrary Initialized with Stub Impl."; | |
1373 } | |
1374 | |
1375 // static | |
1376 void NetworkLibrary::Shutdown() { | |
1377 VLOG(1) << "NetworkLibrary Shutting down..."; | |
1378 delete g_network_library; | |
1379 g_network_library = NULL; | |
1380 VLOG(1) << " NetworkLibrary Shutdown completed."; | |
1381 } | |
1382 | |
1383 // static | |
1384 NetworkLibrary* NetworkLibrary::Get() { | |
1385 return g_network_library; | |
1386 } | |
1387 | |
1388 // static | |
1389 void NetworkLibrary::SetForTesting(NetworkLibrary* library) { | |
1390 if (g_network_library) | |
1391 delete g_network_library; | |
1392 g_network_library = library; | |
1393 } | |
1394 | |
1395 } // namespace chromeos | |
OLD | NEW |