1 // Copyright (c) 2013 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 "chromeos/network/network_connection_handler.h" 6 7 #include "base/bind.h" 8 #include "base/json/json_reader.h" 9 #include "base/location.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "chromeos/cert_loader.h" 13 #include "chromeos/dbus/dbus_thread_manager.h" 14 #include "chromeos/dbus/shill_manager_client.h" 15 #include "chromeos/dbus/shill_service_client.h" 16 #include "chromeos/network/client_cert_util.h" 17 #include "chromeos/network/managed_network_configuration_handler.h" 18 #include "chromeos/network/network_configuration_handler.h" 19 #include "chromeos/network/network_event_log.h" 20 #include "chromeos/network/network_handler_callbacks.h" 21 #include "chromeos/network/network_profile_handler.h" 22 #include "chromeos/network/network_state.h" 23 #include "chromeos/network/network_state_handler.h" 24 #include "chromeos/network/network_ui_data.h" 25 #include "chromeos/network/shill_property_util.h" 26 #include "chromeos/tpm_token_loader.h" 27 #include "dbus/object_path.h" 28 #include "net/cert/x509_certificate.h" 29 #include "third_party/cros_system_api/dbus/service_constants.h" 30 31 namespace chromeos { 32 33 namespace { 34 35 void InvokeErrorCallback(const std::string& service_path, 36 const network_handler::ErrorCallback& error_callback, 37 const std::string& error_name) { 38 NET_LOG_ERROR("Connect Error: " + error_name, service_path); 39 network_handler::RunErrorCallback( 40 error_callback, service_path, error_name, ""); 41 } 42 43 bool IsAuthenticationError(const std::string& error) { 44 return (error == shill::kErrorBadWEPKey || 45 error == shill::kErrorPppAuthFailed || 46 error == shill::kErrorEapLocalTlsFailed || 47 error == shill::kErrorEapRemoteTlsFailed || 48 error == shill::kErrorEapAuthenticationFailed); 49 } 50 51 bool VPNRequiresCredentials(const std::string& service_path, 52 const std::string& provider_type, 53 const base::DictionaryValue& provider_properties) { 54 if (provider_type == shill::kProviderOpenVpn) { 55 std::string username; 56 provider_properties.GetStringWithoutPathExpansion( 57 shill::kOpenVPNUserProperty, &username); 58 if (username.empty()) { 59 NET_LOG_EVENT("OpenVPN: No username", service_path); 60 return true; 61 } 62 bool passphrase_required = false; 63 provider_properties.GetBooleanWithoutPathExpansion( 64 shill::kPassphraseRequiredProperty, &passphrase_required); 65 if (passphrase_required) { 66 NET_LOG_EVENT("OpenVPN: Passphrase Required", service_path); 67 return true; 68 } 69 NET_LOG_EVENT("OpenVPN Is Configured", service_path); 70 } else { 71 bool passphrase_required = false; 72 provider_properties.GetBooleanWithoutPathExpansion( 73 shill::kL2tpIpsecPskRequiredProperty, &passphrase_required); 74 if (passphrase_required) { 75 NET_LOG_EVENT("VPN: PSK Required", service_path); 76 return true; 77 } 78 provider_properties.GetBooleanWithoutPathExpansion( 79 shill::kPassphraseRequiredProperty, &passphrase_required); 80 if (passphrase_required) { 81 NET_LOG_EVENT("VPN: Passphrase Required", service_path); 82 return true; 83 } 84 NET_LOG_EVENT("VPN Is Configured", service_path); 85 } 86 return false; 87 } 88 89 std::string GetDefaultUserProfilePath(const NetworkState* network) { 90 if (!NetworkHandler::IsInitialized() || 91 (LoginState::IsInitialized() && 92 !LoginState::Get()->UserHasNetworkProfile()) || 93 (network && network->type() == shill::kTypeWifi && 94 network->security() == shill::kSecurityNone)) { 95 return NetworkProfileHandler::GetSharedProfilePath(); 96 } 97 const NetworkProfile* profile = 98 NetworkHandler::Get()->network_profile_handler()->GetDefaultUserProfile(); 99 return profile ? profile->path 100 : NetworkProfileHandler::GetSharedProfilePath(); 101 } 102 103 } // namespace 104 105 const char NetworkConnectionHandler::kErrorNotFound[] = "not-found"; 106 const char NetworkConnectionHandler::kErrorConnected[] = "connected"; 107 const char NetworkConnectionHandler::kErrorConnecting[] = "connecting"; 108 const char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected"; 109 const char NetworkConnectionHandler::kErrorPassphraseRequired[] = 110 "passphrase-required"; 111 const char NetworkConnectionHandler::kErrorActivationRequired[] = 112 "activation-required"; 113 const char NetworkConnectionHandler::kErrorCertificateRequired[] = 114 "certificate-required"; 115 const char NetworkConnectionHandler::kErrorConfigurationRequired[] = 116 "configuration-required"; 117 const char NetworkConnectionHandler::kErrorAuthenticationRequired[] = 118 "authentication-required"; 119 const char NetworkConnectionHandler::kErrorShillError[] = "shill-error"; 120 const char NetworkConnectionHandler::kErrorConfigureFailed[] = 121 "configure-failed"; 122 const char NetworkConnectionHandler::kErrorConnectCanceled[] = 123 "connect-canceled"; 124 const char NetworkConnectionHandler::kErrorCertLoadTimeout[] = 125 "cert-load-timeout"; 126 127 struct NetworkConnectionHandler::ConnectRequest { 128 ConnectRequest(const std::string& service_path, 129 const std::string& profile_path, 130 const base::Closure& success, 131 const network_handler::ErrorCallback& error) 132 : service_path(service_path), 133 profile_path(profile_path), 134 connect_state(CONNECT_REQUESTED), 135 success_callback(success), 136 error_callback(error) { 137 } 138 enum ConnectState { 139 CONNECT_REQUESTED = 0, 140 CONNECT_STARTED = 1, 141 CONNECT_CONNECTING = 2 142 }; 143 std::string service_path; 144 std::string profile_path; 145 ConnectState connect_state; 146 base::Closure success_callback; 147 network_handler::ErrorCallback error_callback; 148 }; 149 150 NetworkConnectionHandler::NetworkConnectionHandler() 151 : cert_loader_(NULL), 152 network_state_handler_(NULL), 153 configuration_handler_(NULL), 154 logged_in_(false), 155 certificates_loaded_(false), 156 applied_autoconnect_policy_(false), 157 requested_connect_to_best_network_(false) { 158 } 159 160 NetworkConnectionHandler::~NetworkConnectionHandler() { 161 if (network_state_handler_) 162 network_state_handler_->RemoveObserver(this, FROM_HERE); 163 if (cert_loader_) 164 cert_loader_->RemoveObserver(this); 165 if (LoginState::IsInitialized()) 166 LoginState::Get()->RemoveObserver(this); 167 } 168 169 void NetworkConnectionHandler::Init( 170 NetworkStateHandler* network_state_handler, 171 NetworkConfigurationHandler* network_configuration_handler, 172 ManagedNetworkConfigurationHandler* managed_network_configuration_handler) { 173 if (LoginState::IsInitialized()) 174 LoginState::Get()->AddObserver(this); 175 176 if (CertLoader::IsInitialized()) { 177 cert_loader_ = CertLoader::Get(); 178 cert_loader_->AddObserver(this); 179 if (cert_loader_->certificates_loaded()) { 180 NET_LOG_EVENT("Certificates Loaded", ""); 181 certificates_loaded_ = true; 182 } 183 } else { 184 // TODO(tbarzic): Require a mock or stub cert_loader in tests. 185 NET_LOG_EVENT("Certificate Loader not initialized", ""); 186 certificates_loaded_ = true; 187 } 188 189 if (network_state_handler) { 190 network_state_handler_ = network_state_handler; 191 network_state_handler_->AddObserver(this, FROM_HERE); 192 } 193 configuration_handler_ = network_configuration_handler; 194 195 if (managed_network_configuration_handler) { 196 managed_configuration_handler_ = managed_network_configuration_handler; 197 managed_configuration_handler_->AddObserver(this); 198 } 199 200 // After this point, the NetworkConnectionHandler is fully initialized (all 201 // handler references set, observers registered, ...). 202 203 if (LoginState::IsInitialized()) 204 LoggedInStateChanged(); 205 } 206 207 void NetworkConnectionHandler::LoggedInStateChanged() { 208 LoginState* login_state = LoginState::Get(); 209 if (logged_in_ || !login_state->IsUserLoggedIn()) 210 return; 211 212 NET_LOG_EVENT("Logged In", ""); 213 logged_in_ = true; 214 logged_in_time_ = base::TimeTicks::Now(); 215 216 DisconnectIfPolicyRequires(); 217 } 218 219 void NetworkConnectionHandler::OnCertificatesLoaded( 220 const net::CertificateList& cert_list, 221 bool initial_load) { 222 certificates_loaded_ = true; 223 NET_LOG_EVENT("Certificates Loaded", ""); 224 if (queued_connect_) { 225 ConnectToQueuedNetwork(); 226 } else if (initial_load) { 227 // Connecting to the "best" available network requires certificates to be 228 // loaded. Try to connect now. 229 ConnectToBestNetworkAfterLogin(); 230 } 231 } 232 233 void NetworkConnectionHandler::PolicyChanged(const std::string& userhash) { 234 // Ignore user policies. 235 if (!userhash.empty()) 236 return; 237 DisconnectIfPolicyRequires(); 238 } 239 240 void NetworkConnectionHandler::ConnectToNetwork( 241 const std::string& service_path, 242 const base::Closure& success_callback, 243 const network_handler::ErrorCallback& error_callback, 244 bool check_error_state) { 245 NET_LOG_USER("ConnectToNetwork", service_path); 246 // Clear any existing queued connect request. 247 queued_connect_.reset(); 248 if (HasConnectingNetwork(service_path)) { 249 NET_LOG_USER("Connect Request While Pending", service_path); 250 InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 251 return; 252 } 253 254 // Check cached network state for connected, connecting, or unactivated 255 // networks. These states will not be affected by a recent configuration. 256 // Note: NetworkState may not exist for a network that was recently 257 // configured, in which case these checks do not apply anyway. 258 const NetworkState* network = 259 network_state_handler_->GetNetworkState(service_path); 260 261 if (network) { 262 // For existing networks, perform some immediate consistency checks. 263 if (network->IsConnectedState()) { 264 InvokeErrorCallback(service_path, error_callback, kErrorConnected); 265 return; 266 } 267 if (network->IsConnectingState()) { 268 InvokeErrorCallback(service_path, error_callback, kErrorConnecting); 269 return; 270 } 271 if (network->RequiresActivation()) { 272 InvokeErrorCallback(service_path, error_callback, 273 kErrorActivationRequired); 274 return; 275 } 276 277 if (check_error_state) { 278 const std::string& error = network->last_error(); 279 if (error == shill::kErrorBadPassphrase) { 280 InvokeErrorCallback(service_path, error_callback, error); 281 return; 282 } 283 if (IsAuthenticationError(error)) { 284 InvokeErrorCallback( 285 service_path, error_callback, kErrorAuthenticationRequired); 286 return; 287 } 288 } 289 } 290 291 // If the network does not have a profile path, specify the correct default 292 // profile here and set it once connected. Otherwise leave it empty to 293 // indicate that it does not need to be set. 294 std::string profile_path; 295 if (!network || network->profile_path().empty()) 296 profile_path = GetDefaultUserProfilePath(network); 297 298 // All synchronous checks passed, add |service_path| to connecting list. 299 pending_requests_.insert(std::make_pair( 300 service_path, 301 ConnectRequest(service_path, profile_path, 302 success_callback, error_callback))); 303 304 // Connect immediately to 'connectable' networks. 305 // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 306 if (network && network->connectable() && network->type() != shill::kTypeVPN) { 307 CallShillConnect(service_path); 308 return; 309 } 310 311 // Request additional properties to check. VerifyConfiguredAndConnect will 312 // use only these properties, not cached properties, to ensure that they 313 // are up to date after any recent configuration. 314 configuration_handler_->GetProperties( 315 service_path, 316 base::Bind(&NetworkConnectionHandler::VerifyConfiguredAndConnect, 317 AsWeakPtr(), check_error_state), 318 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 319 AsWeakPtr(), service_path)); 320 } 321 322 void NetworkConnectionHandler::DisconnectNetwork( 323 const std::string& service_path, 324 const base::Closure& success_callback, 325 const network_handler::ErrorCallback& error_callback) { 326 NET_LOG_USER("DisconnectNetwork", service_path); 327 const NetworkState* network = 328 network_state_handler_->GetNetworkState(service_path); 329 if (!network) { 330 InvokeErrorCallback(service_path, error_callback, kErrorNotFound); 331 return; 332 } 333 if (!network->IsConnectedState()) { 334 InvokeErrorCallback(service_path, error_callback, kErrorNotConnected); 335 return; 336 } 337 CallShillDisconnect(service_path, success_callback, error_callback); 338 } 339 340 bool NetworkConnectionHandler::HasConnectingNetwork( 341 const std::string& service_path) { 342 return pending_requests_.count(service_path) != 0; 343 } 344 345 bool NetworkConnectionHandler::HasPendingConnectRequest() { 346 return pending_requests_.size() > 0; 347 } 348 349 void NetworkConnectionHandler::NetworkListChanged() { 350 CheckAllPendingRequests(); 351 } 352 353 void NetworkConnectionHandler::NetworkPropertiesUpdated( 354 const NetworkState* network) { 355 if (HasConnectingNetwork(network->path())) 356 CheckPendingRequest(network->path()); 357 } 358 359 NetworkConnectionHandler::ConnectRequest* 360 NetworkConnectionHandler::GetPendingRequest(const std::string& service_path) { 361 std::map<std::string, ConnectRequest>::iterator iter = 362 pending_requests_.find(service_path); 363 return iter != pending_requests_.end() ? &(iter->second) : NULL; 364 } 365 366 // ConnectToNetwork implementation 367 368 void NetworkConnectionHandler::VerifyConfiguredAndConnect( 369 bool check_error_state, 370 const std::string& service_path, 371 const base::DictionaryValue& service_properties) { 372 NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path); 373 374 // If 'passphrase_required' is still true, then the 'Passphrase' property 375 // has not been set to a minimum length value. 376 bool passphrase_required = false; 377 service_properties.GetBooleanWithoutPathExpansion( 378 shill::kPassphraseRequiredProperty, &passphrase_required); 379 if (passphrase_required) { 380 ErrorCallbackForPendingRequest(service_path, kErrorPassphraseRequired); 381 return; 382 } 383 384 std::string type, security; 385 service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 386 service_properties.GetStringWithoutPathExpansion( 387 shill::kSecurityProperty, &security); 388 bool connectable = false; 389 service_properties.GetBooleanWithoutPathExpansion( 390 shill::kConnectableProperty, &connectable); 391 392 // In case NetworkState was not available in ConnectToNetwork (e.g. it had 393 // been recently configured), we need to check Connectable again. 394 if (connectable && type != shill::kTypeVPN) { 395 // TODO(stevenjb): Shill needs to properly set Connectable for VPN. 396 CallShillConnect(service_path); 397 return; 398 } 399 400 // Get VPN provider type and host (required for configuration) and ensure 401 // that required VPN non-cert properties are set. 402 const base::DictionaryValue* provider_properties = NULL; 403 std::string vpn_provider_type, vpn_provider_host, vpn_client_cert_id; 404 if (type == shill::kTypeVPN) { 405 // VPN Provider values are read from the "Provider" dictionary, not the 406 // "Provider.Type", etc keys (which are used only to set the values). 407 if (service_properties.GetDictionaryWithoutPathExpansion( 408 shill::kProviderProperty, &provider_properties)) { 409 provider_properties->GetStringWithoutPathExpansion( 410 shill::kTypeProperty, &vpn_provider_type); 411 provider_properties->GetStringWithoutPathExpansion( 412 shill::kHostProperty, &vpn_provider_host); 413 provider_properties->GetStringWithoutPathExpansion( 414 shill::kL2tpIpsecClientCertIdProperty, &vpn_client_cert_id); 415 } 416 if (vpn_provider_type.empty() || vpn_provider_host.empty()) { 417 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 418 return; 419 } 420 } 421 422 scoped_ptr<NetworkUIData> ui_data = 423 shill_property_util::GetUIDataFromProperties(service_properties); 424 425 client_cert::ConfigType client_cert_type = client_cert::CONFIG_TYPE_NONE; 426 if (type == shill::kTypeVPN) { 427 if (vpn_provider_type == shill::kProviderOpenVpn) { 428 client_cert_type = client_cert::CONFIG_TYPE_OPENVPN; 429 } else { 430 // L2TP/IPSec only requires a certificate if one is specified in ONC 431 // or one was configured by the UI. Otherwise it is L2TP/IPSec with 432 // PSK and doesn't require a certificate. 433 // 434 // TODO(benchan): Modify shill to specify the authentication type via 435 // the kL2tpIpsecAuthenticationType property, so that Chrome doesn't need 436 // to deduce the authentication type based on the 437 // kL2tpIpsecClientCertIdProperty here (and also in VPNConfigView). 438 if (!vpn_client_cert_id.empty() || 439 (ui_data && ui_data->certificate_type() != CLIENT_CERT_TYPE_NONE)) 440 client_cert_type = client_cert::CONFIG_TYPE_IPSEC; 441 } 442 } else if (type == shill::kTypeWifi && security == shill::kSecurity8021x) { 443 client_cert_type = client_cert::CONFIG_TYPE_EAP; 444 } 445 446 base::DictionaryValue config_properties; 447 if (client_cert_type != client_cert::CONFIG_TYPE_NONE) { 448 // Note: if we get here then a certificate *may* be required, so we want 449 // to ensure that certificates have loaded successfully before attempting 450 // to connect. 451 452 // User must be logged in to connect to a network requiring a certificate. 453 if (!logged_in_ || !cert_loader_) { 454 NET_LOG_ERROR("User not logged in", ""); 455 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 456 return; 457 } 458 // If certificates have not been loaded yet, queue the connect request. 459 if (!certificates_loaded_) { 460 NET_LOG_EVENT("Certificates not loaded", ""); 461 QueueConnectRequest(service_path); 462 return; 463 } 464 465 // If the client certificate must be configured, this will be set to a 466 // non-empty string. 467 std::string pkcs11_id; 468 469 // Check certificate properties in kUIDataProperty if configured. 470 // Note: Wifi/VPNConfigView set these properties explicitly, in which case 471 // only the TPM must be configured. 472 if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) { 473 pkcs11_id = CertificateIsConfigured(ui_data.get()); 474 // Ensure the certificate is available and configured. 475 if (!cert_loader_->IsHardwareBacked() || pkcs11_id.empty()) { 476 ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired); 477 return; 478 } 479 } else if (check_error_state && 480 !client_cert::IsCertificateConfigured(client_cert_type, 481 service_properties)) { 482 // Network may not be configured. 483 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 484 return; 485 } 486 487 // The network may not be 'Connectable' because the TPM properties are not 488 // set up, so configure tpm slot/pin before connecting. 489 if (cert_loader_ && cert_loader_->IsHardwareBacked()) { 490 // Pass NULL if pkcs11_id is empty, so that it doesn't clear any 491 // previously configured client cert. 492 client_cert::SetShillProperties( 493 client_cert_type, 494 base::IntToString(cert_loader_->TPMTokenSlotID()), 495 TPMTokenLoader::Get()->tpm_user_pin(), 496 pkcs11_id.empty() ? NULL : &pkcs11_id, 497 &config_properties); 498 } 499 } 500 501 if (type == shill::kTypeVPN) { 502 // VPN may require a username, and/or passphrase to be set. (Check after 503 // ensuring that any required certificates are configured). 504 DCHECK(provider_properties); 505 if (VPNRequiresCredentials( 506 service_path, vpn_provider_type, *provider_properties)) { 507 NET_LOG_USER("VPN Requires Credentials", service_path); 508 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 509 return; 510 } 511 512 // If it's L2TP/IPsec PSK, there is no properties to configure, so proceed 513 // to connect. 514 if (client_cert_type == client_cert::CONFIG_TYPE_NONE) { 515 CallShillConnect(service_path); 516 return; 517 } 518 } 519 520 if (!config_properties.empty()) { 521 NET_LOG_EVENT("Configuring Network", service_path); 522 configuration_handler_->SetProperties( 523 service_path, 524 config_properties, 525 base::Bind(&NetworkConnectionHandler::CallShillConnect, 526 AsWeakPtr(), 527 service_path), 528 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, 529 AsWeakPtr(), 530 service_path)); 531 return; 532 } 533 534 // Otherwise, we probably still need to configure the network since 535 // 'Connectable' is false. If |check_error_state| is true, signal an 536 // error, otherwise attempt to connect to possibly gain additional error 537 // state from Shill (or in case 'Connectable' is improperly unset). 538 if (check_error_state) 539 ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired); 540 else 541 CallShillConnect(service_path); 542 } 543 544 void NetworkConnectionHandler::QueueConnectRequest( 545 const std::string& service_path) { 546 ConnectRequest* request = GetPendingRequest(service_path); 547 if (!request) { 548 NET_LOG_ERROR("No pending request to queue", service_path); 549 return; 550 } 551 552 const int kMaxCertLoadTimeSeconds = 15; 553 base::TimeDelta dtime = base::TimeTicks::Now() - logged_in_time_; 554 if (dtime > base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds)) { 555 NET_LOG_ERROR("Certificate load timeout", service_path); 556 InvokeErrorCallback(service_path, 557 request->error_callback, 558 kErrorCertLoadTimeout); 559 return; 560 } 561 562 NET_LOG_EVENT("Connect Request Queued", service_path); 563 queued_connect_.reset(new ConnectRequest( 564 service_path, request->profile_path, 565 request->success_callback, request->error_callback)); 566 pending_requests_.erase(service_path); 567 568 // Post a delayed task to check to see if certificates have loaded. If they 569 // haven't, and queued_connect_ has not been cleared (e.g. by a successful 570 // connect request), cancel the request and notify the user. 571 base::MessageLoopProxy::current()->PostDelayedTask( 572 FROM_HERE, 573 base::Bind(&NetworkConnectionHandler::CheckCertificatesLoaded, 574 AsWeakPtr()), 575 base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds) - dtime); 576 } 577 578 void NetworkConnectionHandler::CheckCertificatesLoaded() { 579 if (certificates_loaded_) 580 return; 581 // If queued_connect_ has been cleared (e.g. another connect request occurred 582 // and wasn't queued), do nothing here. 583 if (!queued_connect_) 584 return; 585 // Otherwise, notify the user. 586 NET_LOG_ERROR("Certificate load timeout", queued_connect_->service_path); 587 InvokeErrorCallback(queued_connect_->service_path, 588 queued_connect_->error_callback, 589 kErrorCertLoadTimeout); 590 queued_connect_.reset(); 591 } 592 593 void NetworkConnectionHandler::ConnectToQueuedNetwork() { 594 DCHECK(queued_connect_); 595 596 // Make a copy of |queued_connect_| parameters, because |queued_connect_| 597 // will get reset at the beginning of |ConnectToNetwork|. 598 std::string service_path = queued_connect_->service_path; 599 base::Closure success_callback = queued_connect_->success_callback; 600 network_handler::ErrorCallback error_callback = 601 queued_connect_->error_callback; 602 603 NET_LOG_EVENT("Connecting to Queued Network", service_path); 604 ConnectToNetwork(service_path, success_callback, error_callback, 605 false /* check_error_state */); 606 } 607 608 void NetworkConnectionHandler::CallShillConnect( 609 const std::string& service_path) { 610 NET_LOG_EVENT("Sending Connect Request to Shill", service_path); 611 network_state_handler_->ClearLastErrorForNetwork(service_path); 612 DBusThreadManager::Get()->GetShillServiceClient()->Connect( 613 dbus::ObjectPath(service_path), 614 base::Bind(&NetworkConnectionHandler::HandleShillConnectSuccess, 615 AsWeakPtr(), service_path), 616 base::Bind(&NetworkConnectionHandler::HandleShillConnectFailure, 617 AsWeakPtr(), service_path)); 618 } 619 620 void NetworkConnectionHandler::HandleConfigurationFailure( 621 const std::string& service_path, 622 const std::string& error_name, 623 scoped_ptr<base::DictionaryValue> error_data) { 624 ConnectRequest* request = GetPendingRequest(service_path); 625 if (!request) { 626 NET_LOG_ERROR("HandleConfigurationFailure called with no pending request.", 627 service_path); 628 return; 629 } 630 network_handler::ErrorCallback error_callback = request->error_callback; 631 pending_requests_.erase(service_path); 632 if (!error_callback.is_null()) 633 error_callback.Run(kErrorConfigureFailed, error_data.Pass()); 634 } 635 636 void NetworkConnectionHandler::HandleShillConnectSuccess( 637 const std::string& service_path) { 638 ConnectRequest* request = GetPendingRequest(service_path); 639 if (!request) { 640 NET_LOG_ERROR("HandleShillConnectSuccess called with no pending request.", 641 service_path); 642 return; 643 } 644 request->connect_state = ConnectRequest::CONNECT_STARTED; 645 NET_LOG_EVENT("Connect Request Acknowledged", service_path); 646 // Do not call success_callback here, wait for one of the following 647 // conditions: 648 // * State transitions to a non connecting state indicating success or failure 649 // * Network is no longer in the visible list, indicating failure 650 CheckPendingRequest(service_path); 651 } 652 653 void NetworkConnectionHandler::HandleShillConnectFailure( 654 const std::string& service_path, 655 const std::string& dbus_error_name, 656 const std::string& dbus_error_message) { 657 ConnectRequest* request = GetPendingRequest(service_path); 658 if (!request) { 659 NET_LOG_ERROR("HandleShillConnectFailure called with no pending request.", 660 service_path); 661 return; 662 } 663 network_handler::ErrorCallback error_callback = request->error_callback; 664 pending_requests_.erase(service_path); 665 network_handler::ShillErrorCallbackFunction( 666 shill::kErrorConnectFailed, service_path, error_callback, 667 dbus_error_name, dbus_error_message); 668 } 669 670 void NetworkConnectionHandler::CheckPendingRequest( 671 const std::string service_path) { 672 ConnectRequest* request = GetPendingRequest(service_path); 673 DCHECK(request); 674 if (request->connect_state == ConnectRequest::CONNECT_REQUESTED) 675 return; // Request has not started, ignore update 676 const NetworkState* network = 677 network_state_handler_->GetNetworkState(service_path); 678 if (!network) 679 return; // NetworkState may not be be updated yet. 680 681 if (network->IsConnectingState()) { 682 request->connect_state = ConnectRequest::CONNECT_CONNECTING; 683 return; 684 } 685 if (network->IsConnectedState()) { 686 NET_LOG_EVENT("Connect Request Succeeded", service_path); 687 if (!request->profile_path.empty()) { 688 // If a profile path was specified, set it on a successful connection. 689 configuration_handler_->SetNetworkProfile( 690 service_path, 691 request->profile_path, 692 base::Bind(&base::DoNothing), 693 chromeos::network_handler::ErrorCallback()); 694 } 695 if (!request->success_callback.is_null()) 696 request->success_callback.Run(); 697 pending_requests_.erase(service_path); 698 return; 699 } 700 if (network->connection_state() == shill::kStateIdle && 701 request->connect_state != ConnectRequest::CONNECT_CONNECTING) { 702 // Connection hasn't started yet, keep waiting. 703 return; 704 } 705 706 // Network is neither connecting or connected; an error occurred. 707 std::string error_name; // 'Canceled' or 'Failed' 708 if (network->connection_state() == shill::kStateIdle && 709 pending_requests_.size() > 1) { 710 // Another connect request canceled this one. 711 error_name = kErrorConnectCanceled; 712 } else { 713 error_name = shill::kErrorConnectFailed; 714 if (network->connection_state() != shill::kStateFailure) { 715 NET_LOG_ERROR("Unexpected State: " + network->connection_state(), 716 service_path); 717 } 718 } 719 720 network_handler::ErrorCallback error_callback = request->error_callback; 721 pending_requests_.erase(service_path); 722 if (error_callback.is_null()) { 723 NET_LOG_ERROR("Connect Error, no callback: " + error_name, service_path); 724 return; 725 } 726 InvokeErrorCallback(service_path, error_callback, error_name); 727 } 728 729 void NetworkConnectionHandler::CheckAllPendingRequests() { 730 for (std::map<std::string, ConnectRequest>::iterator iter = 731 pending_requests_.begin(); iter != pending_requests_.end(); ++iter) { 732 CheckPendingRequest(iter->first); 733 } 734 } 735 736 std::string NetworkConnectionHandler::CertificateIsConfigured( 737 NetworkUIData* ui_data) { 738 if (ui_data->certificate_pattern().Empty()) 739 return std::string(); 740 // Find the matching certificate. 741 scoped_refptr<net::X509Certificate> matching_cert = 742 client_cert::GetCertificateMatch(ui_data->certificate_pattern(), 743 cert_loader_->cert_list()); 744 if (!matching_cert.get()) 745 return std::string(); 746 return CertLoader::GetPkcs11IdForCert(*matching_cert.get()); 747 } 748 749 void NetworkConnectionHandler::ErrorCallbackForPendingRequest( 750 const std::string& service_path, 751 const std::string& error_name) { 752 ConnectRequest* request = GetPendingRequest(service_path); 753 if (!request) { 754 NET_LOG_ERROR("ErrorCallbackForPendingRequest with no pending request.", 755 service_path); 756 return; 757 } 758 // Remove the entry before invoking the callback in case it triggers a retry. 759 network_handler::ErrorCallback error_callback = request->error_callback; 760 pending_requests_.erase(service_path); 761 InvokeErrorCallback(service_path, error_callback, error_name); 762 } 763 764 // Disconnect 765 766 void NetworkConnectionHandler::CallShillDisconnect( 767 const std::string& service_path, 768 const base::Closure& success_callback, 769 const network_handler::ErrorCallback& error_callback) { 770 NET_LOG_USER("Disconnect Request", service_path); 771 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( 772 dbus::ObjectPath(service_path), 773 base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, 774 AsWeakPtr(), service_path, success_callback), 775 base::Bind(&network_handler::ShillErrorCallbackFunction, 776 kErrorShillError, service_path, error_callback)); 777 } 778 779 void NetworkConnectionHandler::HandleShillDisconnectSuccess( 780 const std::string& service_path, 781 const base::Closure& success_callback) { 782 NET_LOG_EVENT("Disconnect Request Sent", service_path); 783 if (!success_callback.is_null()) 784 success_callback.Run(); 785 } 786 787 void NetworkConnectionHandler::ConnectToBestNetworkAfterLogin() { 788 if (requested_connect_to_best_network_ || !applied_autoconnect_policy_ || 789 !certificates_loaded_) { 790 return; 791 } 792 793 requested_connect_to_best_network_ = true; 794 network_state_handler_->ConnectToBestWifiNetwork(); 795 } 796 797 void NetworkConnectionHandler::DisconnectIfPolicyRequires() { 798 if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn()) 799 return; 800 801 const base::DictionaryValue* global_network_config = 802 managed_configuration_handler_->GetGlobalConfigFromPolicy(std::string()); 803 if (!global_network_config) 804 return; 805 806 applied_autoconnect_policy_ = true; 807 808 bool only_policy_autoconnect = false; 809 global_network_config->GetBooleanWithoutPathExpansion( 810 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, 811 &only_policy_autoconnect); 812 813 if (!only_policy_autoconnect) 814 return; 815 816 NET_LOG_DEBUG("DisconnectIfPolicyRequires", 817 "Disconnecting unmanaged and shared networks if any exist."); 818 819 // Get the list of unmanaged & shared networks that are connected or 820 // connecting. 821 NetworkStateHandler::NetworkStateList networks; 822 network_state_handler_->GetVisibleNetworkListByType( 823 NetworkTypePattern::Wireless(), &networks); 824 for (NetworkStateHandler::NetworkStateList::const_iterator it = 825 networks.begin(); 826 it != networks.end(); 827 ++it) { 828 const NetworkState* network = *it; 829 if (!(network->IsConnectingState() || network->IsConnectedState())) 830 break; // Connected and connecting networks are listed first. 831 832 if (network->IsPrivate()) 833 continue; 834 835 const bool network_is_policy_managed = 836 !network->profile_path().empty() && !network->guid().empty() && 837 managed_configuration_handler_->FindPolicyByGuidAndProfile( 838 network->guid(), network->profile_path()); 839 if (network_is_policy_managed) 840 continue; 841 842 NET_LOG_EVENT("Disconnect Forced by Policy", network->path()); 843 CallShillDisconnect( 844 network->path(), base::Closure(), network_handler::ErrorCallback()); 845 } 846 847 ConnectToBestNetworkAfterLogin(); 848 } 849 850 } // namespace chromeos 851