Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Unified Diff: chromeos/network/network_connection_handler.cc

Issue 16512003: Configure networks requiring a certificate. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update error strings Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chromeos/network/network_connection_handler.cc
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc
index 97cc9f8d9e25f52aa931ecb1ce3d67fa4c5a21d7..16b90af9d2ecd066f35573d7c3da2bd86850cb81 100644
--- a/chromeos/network/network_connection_handler.cc
+++ b/chromeos/network/network_connection_handler.cc
@@ -100,13 +100,6 @@ bool VPNIsConfigured(const std::string& service_path,
NET_LOG_EVENT("OpenVPN: No passphrase", service_path);
return false;
}
- std::string client_cert_id;
- properties->GetStringWithoutPathExpansion(
- flimflam::kOpenVPNClientCertIdProperty, &client_cert_id);
- if (client_cert_id.empty()) {
- NET_LOG_EVENT("OpenVPN: No cert id", service_path);
- return false;
- }
NET_LOG_EVENT("OpenVPN Is Configured", service_path);
} else {
bool passphrase_required = false;
@@ -122,27 +115,6 @@ bool VPNIsConfigured(const std::string& service_path,
return true;
}
-bool CertificateIsConfigured(NetworkUIData* ui_data) {
- if (ui_data->certificate_type() != CLIENT_CERT_TYPE_PATTERN)
- return true; // No certificate or a reference.
- if (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY) {
- // We skip checking certificate patterns for device policy ONC so that an
- // unmanaged user can't get to the place where a cert is presented for them
- // involuntarily.
- return true;
- }
- if (ui_data->certificate_pattern().Empty())
- return false;
-
- // Find the matching certificate.
- scoped_refptr<net::X509Certificate> matching_cert =
- certificate_pattern::GetCertificateMatch(
- ui_data->certificate_pattern());
- if (!matching_cert.get())
- return false;
- return true;
-}
-
} // namespace
const char NetworkConnectionHandler::kErrorNotFound[] = "not-found";
@@ -162,9 +134,11 @@ const char NetworkConnectionHandler::kErrorConnectFailed[] = "connect-failed";
const char NetworkConnectionHandler::kErrorUnknown[] = "unknown-error";
struct NetworkConnectionHandler::ConnectRequest {
- ConnectRequest(const base::Closure& success,
+ ConnectRequest(const std::string& service_path,
+ const base::Closure& success,
const network_handler::ErrorCallback& error)
- : connect_state(CONNECT_REQUESTED),
+ : service_path(service_path),
+ connect_state(CONNECT_REQUESTED),
success_callback(success),
error_callback(error) {
}
@@ -173,29 +147,44 @@ struct NetworkConnectionHandler::ConnectRequest {
CONNECT_STARTED = 1,
CONNECT_CONNECTING = 2
};
+ std::string service_path;
ConnectState connect_state;
base::Closure success_callback;
network_handler::ErrorCallback error_callback;
};
NetworkConnectionHandler::NetworkConnectionHandler()
- : network_state_handler_(NULL),
- network_configuration_handler_(NULL) {
- const char* new_handler_enabled =
- CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kUseNewNetworkConnectionHandler) ?
- "enabled" : "disabled";
- NET_LOG_EVENT("NewNetworkConnectionHandler", new_handler_enabled);
+ : cert_loader_(NULL),
+ network_state_handler_(NULL),
+ network_configuration_handler_(NULL),
+ logged_in_(false),
+ certificates_loaded_(false) {
}
NetworkConnectionHandler::~NetworkConnectionHandler() {
if (network_state_handler_)
network_state_handler_->RemoveObserver(this);
+ if (cert_loader_)
+ cert_loader_->RemoveObserver(this);
+ if (LoginState::IsInitialized())
+ LoginState::Get()->RemoveObserver(this);
}
void NetworkConnectionHandler::Init(
+ CertLoader* cert_loader,
NetworkStateHandler* network_state_handler,
NetworkConfigurationHandler* network_configuration_handler) {
+ LoginState::Get()->AddObserver(this);
+ logged_in_ =
+ LoginState::Get()->GetLoggedInState() == LoginState::LOGGED_IN_ACTIVE;
+ if (cert_loader) {
+ cert_loader_ = cert_loader;
+ cert_loader_->AddObserver(this);
+ certificates_loaded_ = cert_loader->certificates_loaded();
+ } else {
+ // TODO(stevenjb): Require a mock or stub cert_loader in tests.
+ certificates_loaded_ = true;
+ }
if (network_state_handler) {
network_state_handler_ = network_state_handler;
network_state_handler_->AddObserver(this);
@@ -203,12 +192,44 @@ void NetworkConnectionHandler::Init(
network_configuration_handler_ = network_configuration_handler;
}
+void NetworkConnectionHandler::LoggedInStateChanged(
+ LoginState::LoggedInState state) {
+ NET_LOG_EVENT("NewNetworkConnectionHandler",
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kUseNewNetworkConnectionHandler) ?
+ "enabled" : "disabled");
+ if (state == LoginState::LOGGED_IN_ACTIVE) {
+ logged_in_ = true;
+ NET_LOG_EVENT("Logged In", "");
+ }
+}
+
+void NetworkConnectionHandler::OnCertificatesLoaded(
+ const net::CertificateList& cert_list,
+ bool initial_load) {
+ certificates_loaded_ = true;
+ NET_LOG_EVENT("Certificates Loaded", "");
+ if (queued_connect_) {
+ NET_LOG_EVENT("Connecting to Queued Network",
+ queued_connect_->service_path);
+ ConnectToNetwork(queued_connect_->service_path,
+ queued_connect_->success_callback,
+ queued_connect_->error_callback,
+ true /* ignore_error_state */);
+ } else if (initial_load) {
+ // Once certificates have loaded, connect to the "best" available network.
+ NetworkHandler::Get()->network_state_handler()->ConnectToBestWifiNetwork();
+ }
+}
+
void NetworkConnectionHandler::ConnectToNetwork(
const std::string& service_path,
const base::Closure& success_callback,
const network_handler::ErrorCallback& error_callback,
bool ignore_error_state) {
NET_LOG_USER("ConnectToNetwork", service_path);
+ // Clear any existing queued connect request.
+ queued_connect_.reset();
const NetworkState* network =
network_state_handler_->GetNetworkState(service_path);
if (!network) {
@@ -257,9 +278,11 @@ void NetworkConnectionHandler::ConnectToNetwork(
// All synchronous checks passed, add |service_path| to connecting list.
pending_requests_.insert(std::make_pair(
- service_path, ConnectRequest(success_callback, error_callback)));
+ service_path,
+ ConnectRequest(service_path, success_callback, error_callback)));
- if (!NetworkConnectable(network) && NetworkMayNeedCredentials(network)) {
+ if (!NetworkConnectable(network) &&
+ NetworkMayNeedCredentials(network)) {
// Request additional properties to check.
network_configuration_handler_->GetProperties(
network->path(),
@@ -320,43 +343,101 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect(
const std::string& service_path,
const base::DictionaryValue& properties) {
NET_LOG_EVENT("VerifyConfiguredAndConnect", service_path);
- ConnectRequest* request = pending_request(service_path);
- DCHECK(request);
- network_handler::ErrorCallback error_callback = request->error_callback;
const NetworkState* network =
network_state_handler_->GetNetworkState(service_path);
if (!network) {
- pending_requests_.erase(service_path);
- InvokeErrorCallback(service_path, error_callback, kErrorNotFound);
+ ErrorCallbackForPendingRequest(service_path, kErrorNotFound);
return;
}
// VPN requires a host and username to be set.
if (network->type() == flimflam::kTypeVPN &&
!VPNIsConfigured(service_path, properties)) {
- pending_requests_.erase(service_path);
- InvokeErrorCallback(service_path, error_callback,
- kErrorConfigurationRequired);
+ ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
return;
}
// Check certificate properties in kUIDataProperty.
scoped_ptr<NetworkUIData> ui_data =
ManagedNetworkConfigurationHandler::GetUIData(properties);
- if (ui_data && !CertificateIsConfigured(ui_data.get())) {
- pending_requests_.erase(service_path);
- InvokeErrorCallback(service_path, error_callback,
- kErrorCertificateRequired);
- return;
+ if (ui_data && ui_data->certificate_type() == CLIENT_CERT_TYPE_PATTERN) {
+ // User must be logged in to connect to a network requiring a certificate.
+ if (!logged_in_ || !cert_loader_) {
+ ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
+ return;
+ }
+ // If certificates have not been loaded yet, queue the connect request.
+ if (!certificates_loaded_) {
+ ConnectRequest* request = pending_request(service_path);
+ DCHECK(request);
+ NET_LOG_EVENT("Connect Request Queued", service_path);
+ queued_connect_.reset(new ConnectRequest(
+ service_path, request->success_callback, request->error_callback));
+ pending_requests_.erase(service_path);
+ return;
+ }
+
+ // Ensure the certificate is available.
+ std::string pkcs11_id;
+ if (!CertificateIsConfigured(ui_data.get(), &pkcs11_id)) {
+ ErrorCallbackForPendingRequest(service_path, kErrorCertificateRequired);
+ return;
+ }
+
+ // The network may not be 'Connectable' because the certificate data is
+ // not set up, so configure tpm slot/pin and pkcs11_id before connecting.
+ // TODO(stevenjb): Remove this code once NetworkConfigurationHandler
+ // handles this.
+ NET_LOG_EVENT("Configuring Network", service_path);
+ const std::string& tpm_slot = cert_loader_->tpm_token_slot();
+ const std::string& tpm_pin = cert_loader_->tpm_user_pin();
+ base::DictionaryValue config_properties;
+ network->GetConfigProperties(&config_properties);
+
+ if (network->type() == flimflam::kTypeVPN) {
+ std::string provider_type;
+ properties.GetString(flimflam::kTypeProperty, &provider_type);
+ if (provider_type == flimflam::kProviderOpenVpn) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNClientCertSlotProperty, tpm_slot);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNPinProperty, tpm_pin);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kOpenVPNClientCertIdProperty, pkcs11_id);
+ } else {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecClientCertSlotProperty, tpm_slot);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecPinProperty, tpm_pin);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kL2tpIpsecClientCertIdProperty, pkcs11_id);
+ }
+ } else if (network->type() == flimflam::kTypeWifi) {
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kEapPinProperty, cert_loader_->tpm_user_pin());
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kEapCertIdProperty, pkcs11_id);
+ config_properties.SetStringWithoutPathExpansion(
+ flimflam::kEapKeyIdProperty, pkcs11_id);
+ }
+ network_configuration_handler_->SetProperties(
+ service_path,
+ config_properties,
+ base::Bind(&NetworkConnectionHandler::CallShillConnect,
+ AsWeakPtr(), service_path),
+ base::Bind(&NetworkConnectionHandler::HandleConfigurationFailure,
+ AsWeakPtr(), service_path));
+ return;
}
- CallShillConnect(service_path);
+ // Otherwise, we need to configure the network.
+ ErrorCallbackForPendingRequest(service_path, kErrorConfigurationRequired);
}
void NetworkConnectionHandler::CallShillConnect(
const std::string& service_path) {
- NET_LOG_EVENT("Connect Request", service_path);
+ NET_LOG_EVENT("Sending Connect Request to Shill", service_path);
DBusThreadManager::Get()->GetShillServiceClient()->Connect(
dbus::ObjectPath(service_path),
base::Bind(&NetworkConnectionHandler::HandleShillConnectSuccess,
@@ -382,7 +463,7 @@ void NetworkConnectionHandler::HandleShillConnectSuccess(
ConnectRequest* request = pending_request(service_path);
DCHECK(request);
request->connect_state = ConnectRequest::CONNECT_STARTED;
- NET_LOG_EVENT("Connect Request Sent", service_path);
+ NET_LOG_EVENT("Connect Request Acknowledged", service_path);
// Do not call success_callback here, wait for one of the following
// conditions:
// * State transitions to a non connecting state indicating succes or failure
@@ -412,9 +493,7 @@ void NetworkConnectionHandler::CheckPendingRequest(
const NetworkState* network =
network_state_handler_->GetNetworkState(service_path);
if (!network) {
- network_handler::ErrorCallback error_callback = request->error_callback;
- pending_requests_.erase(service_path);
- InvokeErrorCallback(service_path, error_callback, kErrorNotFound);
+ ErrorCallbackForPendingRequest(service_path, kErrorNotFound);
return;
}
if (network->IsConnectingState()) {
@@ -462,6 +541,31 @@ void NetworkConnectionHandler::CheckAllPendingRequests() {
}
}
+bool NetworkConnectionHandler::CertificateIsConfigured(NetworkUIData* ui_data,
+ std::string* pkcs11_id) {
+ if (ui_data->certificate_pattern().Empty())
+ return false;
+
+ // Find the matching certificate.
+ scoped_refptr<net::X509Certificate> matching_cert =
+ certificate_pattern::GetCertificateMatch(ui_data->certificate_pattern());
+ if (!matching_cert.get())
+ return false;
+ *pkcs11_id = cert_loader_->GetPkcs11IdForCert(*matching_cert.get());
+ return true;
+}
+
+void NetworkConnectionHandler::ErrorCallbackForPendingRequest(
+ const std::string& service_path,
+ const std::string& error_name) {
+ ConnectRequest* request = pending_request(service_path);
+ DCHECK(request);
+ // Remove the entry before invoking the callback in case it triggers a retry.
+ network_handler::ErrorCallback error_callback = request->error_callback;
+ pending_requests_.erase(service_path);
+ InvokeErrorCallback(service_path, error_callback, error_name);
+}
+
// Disconnect
void NetworkConnectionHandler::CallShillDisconnect(
« no previous file with comments | « chromeos/network/network_connection_handler.h ('k') | chromeos/network/network_connection_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698