Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "chromeos/dbus/dbus_thread_manager.h" | |
| 9 #include "chromeos/dbus/shill_manager_client.h" | |
| 10 #include "chromeos/dbus/shill_service_client.h" | |
| 11 #include "chromeos/network/cert_loader.h" | |
| 12 #include "chromeos/network/certificate_pattern_matcher.h" | |
| 13 #include "chromeos/network/network_configuration_handler.h" | |
| 14 #include "chromeos/network/network_event_log.h" | |
| 15 #include "chromeos/network/network_handler_callbacks.h" | |
| 16 #include "chromeos/network/network_state.h" | |
| 17 #include "chromeos/network/network_state_handler.h" | |
| 18 #include "chromeos/network/network_ui_data.h" | |
| 19 #include "dbus/object_path.h" | |
| 20 #include "net/cert/x509_certificate.h" | |
| 21 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 22 | |
| 23 namespace { | |
| 24 const char kLogModule[] = "NetworkConnectionHandler"; | |
| 25 } | |
| 26 | |
| 27 namespace chromeos { | |
| 28 | |
| 29 NetworkConnectionHandler* g_connection_handler_instance = NULL; | |
| 30 | |
| 31 const char NetworkConnectionHandler::kNetworkNotFound[] = "not-found"; | |
| 32 const char NetworkConnectionHandler::kConnected[] = "connected"; | |
| 33 const char NetworkConnectionHandler::kConnecting[] = "connecting"; | |
| 34 const char NetworkConnectionHandler::kNotConnected[] = "not-connected"; | |
| 35 const char NetworkConnectionHandler::kPassphraseRequired[] = | |
| 36 "passphrase-required"; | |
| 37 const char NetworkConnectionHandler::kActivationRequired[] = | |
| 38 "activation-required"; | |
| 39 const char NetworkConnectionHandler::kCertificateRequired[] = | |
| 40 "certificate-required"; | |
| 41 const char NetworkConnectionHandler::kConfigurationRequired[] = | |
| 42 "configuration-required"; | |
| 43 const char NetworkConnectionHandler::kShillError[] = "shill-error"; | |
| 44 | |
| 45 // static | |
| 46 void NetworkConnectionHandler::Initialize() { | |
| 47 CHECK(!g_connection_handler_instance); | |
| 48 g_connection_handler_instance = new NetworkConnectionHandler; | |
| 49 } | |
| 50 | |
| 51 // static | |
| 52 void NetworkConnectionHandler::Shutdown() { | |
| 53 CHECK(g_connection_handler_instance); | |
| 54 delete g_connection_handler_instance; | |
| 55 g_connection_handler_instance = NULL; | |
| 56 } | |
| 57 | |
| 58 // static | |
| 59 NetworkConnectionHandler* NetworkConnectionHandler::Get() { | |
| 60 CHECK(g_connection_handler_instance) | |
| 61 << "NetworkConnectionHandler::Get() called before Initialize()"; | |
| 62 return g_connection_handler_instance; | |
| 63 } | |
| 64 | |
| 65 NetworkConnectionHandler::NetworkConnectionHandler() { | |
| 66 } | |
| 67 | |
| 68 NetworkConnectionHandler::~NetworkConnectionHandler() { | |
| 69 } | |
| 70 | |
| 71 void NetworkConnectionHandler::ConnectToNetwork( | |
| 72 const std::string& service_path, | |
| 73 const base::Closure& success_callback, | |
| 74 const network_handler::ErrorCallback& error_callback) { | |
| 75 const NetworkState* network = | |
| 76 NetworkStateHandler::Get()->GetNetworkState(service_path); | |
| 77 if (!network) { | |
| 78 InvokeErrorCallback(service_path, error_callback, kNetworkNotFound); | |
| 79 return; | |
| 80 } | |
| 81 if (network->IsConnectedState()) { | |
| 82 InvokeErrorCallback(service_path, error_callback, kConnected); | |
| 83 return; | |
| 84 } | |
| 85 if (network->IsConnectingState() || | |
| 86 pending_requests_.find(service_path) != pending_requests_.end()) { | |
| 87 InvokeErrorCallback(service_path, error_callback, kConnecting); | |
| 88 return; | |
| 89 } | |
| 90 if (network->passphrase_required()) { | |
| 91 InvokeErrorCallback(service_path, error_callback, kPassphraseRequired); | |
| 92 return; | |
| 93 } | |
| 94 if (NetworkRequiresActivation(network)) { | |
| 95 InvokeErrorCallback(service_path, error_callback, kActivationRequired); | |
| 96 return; | |
| 97 } | |
| 98 | |
| 99 // All synchronous checks passed, add |service_path| to connecting list. | |
| 100 pending_requests_.insert(service_path); | |
| 101 | |
| 102 if (!network->connectable() && NetworkMayNeedCredentials(network)) { | |
| 103 // Request additional properties to check. | |
| 104 NetworkConfigurationHandler::Get()->GetProperties( | |
| 105 network->path(), | |
| 106 base::Bind(&NetworkConnectionHandler::GetPropertiesCallback, | |
| 107 AsWeakPtr(), success_callback, error_callback), | |
| 108 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, | |
| 109 AsWeakPtr(), network->path(), error_callback)); | |
| 110 return; | |
| 111 } | |
| 112 // All checks passed, send connect request. | |
| 113 CallShillConnect(service_path, success_callback, error_callback); | |
| 114 } | |
| 115 | |
| 116 void NetworkConnectionHandler::DisconnectNetwork( | |
| 117 const std::string& service_path, | |
| 118 const base::Closure& success_callback, | |
| 119 const network_handler::ErrorCallback& error_callback) { | |
| 120 const NetworkState* network = | |
| 121 NetworkStateHandler::Get()->GetNetworkState(service_path); | |
| 122 if (!network) { | |
| 123 InvokeErrorCallback(service_path, error_callback, kNetworkNotFound); | |
| 124 return; | |
| 125 } | |
| 126 if (!network->IsConnectedState()) { | |
| 127 InvokeErrorCallback(service_path, error_callback, kNotConnected); | |
| 128 return; | |
| 129 } | |
| 130 CallShillDisconnect(service_path, success_callback, error_callback); | |
| 131 } | |
| 132 | |
| 133 void NetworkConnectionHandler::CallShillConnect( | |
| 134 const std::string& service_path, | |
| 135 const base::Closure& success_callback, | |
| 136 const network_handler::ErrorCallback& error_callback) { | |
| 137 // TODO(stevenjb): Remove SetConnectingNetwork and use this class to maintain | |
| 138 // the connecting network(s) once NetworkLibrary path is eliminated. | |
| 139 NetworkStateHandler::Get()->SetConnectingNetwork(service_path); | |
| 140 network_event_log::AddEntry(kLogModule, "Connect Request", service_path); | |
| 141 DBusThreadManager::Get()->GetShillServiceClient()->Connect( | |
| 142 dbus::ObjectPath(service_path), | |
| 143 base::Bind(&NetworkConnectionHandler::HandleShillSuccess, | |
| 144 AsWeakPtr(), service_path, success_callback), | |
| 145 base::Bind(&NetworkConnectionHandler::HandleShillFailure, | |
| 146 AsWeakPtr(), service_path, error_callback)); | |
| 147 } | |
| 148 | |
| 149 void NetworkConnectionHandler::CallShillDisconnect( | |
| 150 const std::string& service_path, | |
| 151 const base::Closure& success_callback, | |
| 152 const network_handler::ErrorCallback& error_callback) { | |
| 153 network_event_log::AddEntry(kLogModule, "Disconnect Request", service_path); | |
| 154 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect( | |
| 155 dbus::ObjectPath(service_path), | |
| 156 base::Bind(&NetworkConnectionHandler::HandleShillSuccess, | |
| 157 AsWeakPtr(), service_path, success_callback), | |
| 158 base::Bind(&NetworkConnectionHandler::HandleShillFailure, | |
| 159 AsWeakPtr(), service_path, error_callback)); | |
| 160 } | |
| 161 | |
| 162 void NetworkConnectionHandler::InvokeErrorCallback( | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
cc-local
stevenjb
2013/05/08 01:57:22
Done.
| |
| 163 const std::string& service_path, | |
| 164 const network_handler::ErrorCallback& error_callback, | |
| 165 const std::string& error_name) { | |
| 166 std::string error_message = "Connect Error: " + error_name; | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
These error_messages are so useless. Not only here
stevenjb
2013/05/08 01:57:22
I'm not quite sure what your complaint is, I have
pneubeck (no reviews)
2013/05/08 08:07:46
In many places of chrome where we create (not forw
stevenjb
2013/05/08 18:48:00
I see. In this case, it is helpful to know that th
| |
| 167 network_handler::ShillErrorCallbackFunction( | |
| 168 kLogModule, service_path, error_callback, error_name, error_message); | |
| 169 } | |
| 170 | |
| 171 bool NetworkConnectionHandler::NetworkMayNeedCredentials( | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
cc-local
stevenjb
2013/05/08 01:57:22
Done.
| |
| 172 const NetworkState* network) const { | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
should be
const NetworkState&
stevenjb
2013/05/08 01:57:22
Even though cost& is generally preferred, const* i
| |
| 173 if (network->type() == flimflam::kTypeWifi && | |
| 174 (network->security() == flimflam::kSecurity8021x || | |
| 175 network->security() == flimflam::kSecurityWep /* For dynamic WEP*/)) | |
| 176 return true; | |
| 177 if (network->type() == flimflam::kTypeVPN) | |
| 178 return true; | |
| 179 return false; | |
| 180 } | |
| 181 | |
| 182 bool NetworkConnectionHandler::NetworkRequiresActivation( | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
cc-local
stevenjb
2013/05/08 01:57:22
Done.
| |
| 183 const NetworkState* network) const { | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
should be
const NetworkState&
stevenjb
2013/05/08 01:57:22
ditto.
| |
| 184 return (network->type() == flimflam::kTypeCellular && | |
| 185 (network->activation_state() != flimflam::kActivationStateActivated || | |
| 186 network->cellular_out_of_credits())); | |
| 187 } | |
| 188 | |
| 189 void NetworkConnectionHandler::GetPropertiesCallback( | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
this should use ONC as the NetworkConfigurationHan
stevenjb
2013/05/08 01:57:22
I don't fully understand your comment.
I am fine
pneubeck (no reviews)
2013/05/08 08:07:46
NetworkConfigurationHandler::GetProperties returns
stevenjb
2013/05/08 18:48:00
I see. Somehow I didn't realize that. OK, I'll swi
pneubeck (no reviews)
2013/05/13 09:29:35
yes, fine with me.
| |
| 190 const base::Closure& success_callback, | |
| 191 const network_handler::ErrorCallback& error_callback, | |
| 192 const std::string& service_path, | |
| 193 const base::DictionaryValue& properties) { | |
| 194 const NetworkState* network = | |
| 195 NetworkStateHandler::Get()->GetNetworkState(service_path); | |
| 196 if (!network) { | |
| 197 InvokeErrorCallback(service_path, error_callback, kNetworkNotFound); | |
| 198 return; | |
| 199 } | |
| 200 | |
| 201 std::string provider_type; // For VPN | |
| 202 // Note: we use Value path expansion to extract Provider.Type. | |
| 203 properties.GetString(flimflam::kProviderTypeProperty, &provider_type); | |
| 204 | |
| 205 // VPN requires a host and username to be set. | |
| 206 if (network->type() == flimflam::kTypeVPN) { | |
| 207 std::string hostname; | |
| 208 properties.GetString(flimflam::kProviderHostProperty, &hostname); | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
I'm strongly against adding general configuration
stevenjb
2013/05/08 01:57:22
I am duplicating the logic from NetworkLibrary. I
pneubeck (no reviews)
2013/05/13 09:29:35
then better add a comment that this code is prelim
| |
| 209 bool config_required; | |
| 210 if (provider_type == flimflam::kProviderOpenVpn) { | |
| 211 std::string username, client_cert_id; | |
| 212 properties.GetStringWithoutPathExpansion( | |
| 213 flimflam::kOpenVPNUserProperty, &username); | |
| 214 properties.GetStringWithoutPathExpansion( | |
| 215 flimflam::kOpenVPNClientCertIdProperty, &client_cert_id); | |
| 216 config_required = | |
| 217 hostname.empty() || username.empty() || client_cert_id.empty(); | |
| 218 } else { | |
| 219 bool passphrase_required = false; | |
| 220 std::string passphrase; | |
| 221 properties.GetBooleanWithoutPathExpansion( | |
| 222 flimflam::kL2tpIpsecPskRequiredProperty, &passphrase_required); | |
| 223 properties.GetStringWithoutPathExpansion( | |
| 224 flimflam::kL2tpIpsecPskProperty, &passphrase); | |
| 225 config_required = passphrase_required && passphrase.empty(); | |
| 226 } | |
| 227 if (config_required) { | |
| 228 InvokeErrorCallback(service_path, error_callback, kConfigurationRequired); | |
| 229 return; | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 // Get certificate properties from kUIDataProperty. | |
| 234 scoped_ptr<NetworkUIData> ui_data = | |
| 235 NetworkUIData::CreateUIDataFromShill(properties); | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
UIData is and should be read by the config handler
stevenjb
2013/05/08 01:57:22
Same comment as above - that sounds like a good fo
pneubeck (no reviews)
2013/05/13 09:29:35
then also add a comment here, please.
| |
| 236 if (!ui_data.get()) { | |
| 237 std::string error_message = "Error parsing UIData"; | |
| 238 HandleShillFailure( | |
| 239 service_path, error_callback, kConfigurationRequired, error_message); | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
is that really "ConfigurationRequired"
stevenjb
2013/05/08 01:57:22
I screwed up this logic; what were intended to be
| |
| 240 return; | |
| 241 } | |
| 242 if (ui_data->certificate_type() != CLIENT_CERT_TYPE_PATTERN || | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
Why is that an error? Certificate references shoul
| |
| 243 ui_data->certificate_pattern().Empty()) { | |
| 244 InvokeErrorCallback(service_path, error_callback, kConfigurationRequired); | |
| 245 return; | |
| 246 } | |
| 247 | |
| 248 // We skip certificate patterns for device policy ONC so that an unmanaged | |
| 249 // user can't get to the place where a cert is presented for them | |
| 250 // involuntarily. | |
| 251 if (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY) { | |
| 252 InvokeErrorCallback(service_path, error_callback, kConfigurationRequired); | |
| 253 return; | |
| 254 } | |
| 255 | |
| 256 // Find the matching certificate. | |
| 257 scoped_refptr<net::X509Certificate> matching_cert = | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
I don't like this code to be here: investigating c
stevenjb
2013/05/08 01:57:22
This also seems like something that can be improve
| |
| 258 certificate_pattern::GetCertificateMatch(ui_data->certificate_pattern()); | |
| 259 if (!matching_cert.get()) { | |
| 260 InvokeErrorCallback(service_path, error_callback, kCertificateRequired); | |
| 261 return; | |
| 262 } | |
| 263 | |
| 264 // Set the appropriate propeties, then call connect on success. | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
nit: propeties -> properties
| |
| 265 std::string pkcs11_id = | |
| 266 CertLoader::Get()->GetPkcs11IdForCert(*matching_cert.get()); | |
| 267 base::DictionaryValue new_properties; | |
| 268 network->GetConfigProperties(&new_properties); | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
why is this necessary?
| |
| 269 if (network->type() == flimflam::kTypeWifi) { | |
| 270 // shill requires both CertID and KeyID for TLS connections. | |
| 271 new_properties.SetStringWithoutPathExpansion( | |
| 272 flimflam::kEapCertIdProperty, pkcs11_id); | |
| 273 new_properties.SetStringWithoutPathExpansion( | |
| 274 flimflam::kEapKeyIdProperty, pkcs11_id); | |
| 275 if (network->security() == flimflam::kSecurity8021x) { | |
| 276 new_properties.SetStringWithoutPathExpansion( | |
| 277 flimflam::kEapPinProperty, CertLoader::Get()->tpm_user_pin()); | |
| 278 } | |
| 279 } else if (network->type() == flimflam::kTypeVPN) { | |
| 280 if (provider_type == flimflam::kProviderOpenVpn) { | |
| 281 new_properties.SetStringWithoutPathExpansion( | |
| 282 flimflam::kOpenVPNClientCertIdProperty, pkcs11_id); | |
| 283 new_properties.SetStringWithoutPathExpansion( | |
| 284 flimflam::kOpenVPNPinProperty, | |
| 285 CertLoader::Get()->tpm_user_pin()); | |
| 286 new_properties.SetStringWithoutPathExpansion( | |
| 287 flimflam::kOpenVPNClientCertSlotProperty, | |
| 288 CertLoader::Get()->tpm_token_slot()); | |
| 289 } else { | |
| 290 new_properties.SetStringWithoutPathExpansion( | |
| 291 flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id); | |
| 292 new_properties.SetStringWithoutPathExpansion( | |
| 293 flimflam::kL2tpIpsecPinProperty, | |
| 294 CertLoader::Get()->tpm_user_pin()); | |
| 295 new_properties.SetStringWithoutPathExpansion( | |
| 296 flimflam::kL2tpIpsecClientCertSlotProperty, | |
| 297 CertLoader::Get()->tpm_token_slot()); | |
| 298 } | |
| 299 } | |
| 300 NetworkConfigurationHandler::Get()->SetProperties( | |
|
pneubeck (no reviews)
2013/05/07 08:46:39
CertId, KeyId, Pin, ... are not configuration prop
stevenjb
2013/05/08 01:57:22
I removed the configuration from this flow, as I m
| |
| 301 network->path(), | |
| 302 new_properties, | |
| 303 base::Bind(&NetworkConnectionHandler::CallShillConnect, | |
| 304 AsWeakPtr(), network->path(), | |
| 305 success_callback, error_callback), | |
| 306 base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure, | |
| 307 AsWeakPtr(), network->path(), error_callback)); | |
| 308 } | |
| 309 | |
| 310 void NetworkConnectionHandler::HandleConfigurationFailure( | |
| 311 const std::string& service_path, | |
| 312 const network_handler::ErrorCallback& error_callback, | |
| 313 const std::string& error_name, | |
| 314 scoped_ptr<base::DictionaryValue> error_data) { | |
| 315 pending_requests_.erase(service_path); | |
| 316 if (!error_callback.is_null()) | |
| 317 error_callback.Run(error_name, error_data.Pass()); | |
| 318 } | |
| 319 | |
| 320 void NetworkConnectionHandler::HandleShillSuccess( | |
| 321 const std::string& service_path, | |
| 322 const base::Closure& success_callback) { | |
| 323 // TODO(stevenjb): Currently, this only indicates that the connect request | |
| 324 // succeeded. It might be preferable to wait for the actually connect | |
| 325 // attempt to succeed or fail here and only call |success_callback| at that | |
| 326 // point (or maybe call it twice, once indicating in-progress, then success | |
| 327 // or failure). | |
| 328 pending_requests_.erase(service_path); | |
| 329 network_event_log::AddEntry(kLogModule, "Connected", service_path); | |
| 330 success_callback.Run(); | |
| 331 } | |
| 332 | |
| 333 void NetworkConnectionHandler::HandleShillFailure( | |
| 334 const std::string& service_path, | |
| 335 const network_handler::ErrorCallback& error_callback, | |
| 336 const std::string& error_name, | |
| 337 const std::string& error_message) { | |
| 338 pending_requests_.erase(service_path); | |
| 339 std::string error = "Connect Failure: " + error_name + ": " + error_message; | |
| 340 network_handler::ShillErrorCallbackFunction( | |
| 341 kLogModule, service_path, error_callback, error_name, error_message); | |
| 342 } | |
| 343 | |
| 344 } // namespace chromeos | |
| OLD | NEW |