blob: 3c1c5f324c243612f803dbbf86964cdff8f034ef [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_NET_SYSTEM_PROXY_MANAGER_H_
#define CHROME_BROWSER_ASH_NET_SYSTEM_PROXY_MANAGER_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/extensions/api/settings_private/prefs_util.h"
#include "chromeos/ash/components/dbus/system_proxy/system_proxy_service.pb.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"
#include "content/public/browser/content_browser_client.h"
#include "net/base/auth.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace content {
class LoginDelegate;
} // namespace content
namespace system_proxy {
class SetAuthenticationDetailsResponse;
class ShutDownResponse;
} // namespace system_proxy
namespace views {
class Widget;
} // namespace views
class PrefRegistrySimple;
class PrefService;
class PrefChangeRegistrar;
class Profile;
namespace ash {
class NetworkStateHandler;
class RequestSystemProxyCredentialsView;
class SystemProxyNotification;
// Starts and stops the system-proxy service and handles the authentication
// requests coming from system-proxy. Authentication requests are resolved by
// requesting proxy credentials from the NetworkService or, if the
// NetworkService doesn't have credentials for the specified proxy, it will
// prompt a dialog asking the user for credentials.
// It also listens for the `WorkerActive` dbus signal sent by the System-proxy
// daemon and stores connection information regarding the active worker
// processes.
// TODO(acostinas, https://crbug.com/1145174): Move the logic that tracks
// managed network changes to another class.
class SystemProxyManager : public NetworkStateHandlerObserver {
public:
enum class SystemProxyState {
// System-proxy is not enabled by feature nor policy.
kDisabled = 0,
// System proxy is enabled via feature flag; only available to system
// services which explicitly opt to use system-proxy.
kEnabledForSystemServices,
// System proxy is enabled via policy for all system services and the
// PlayStore.
kEnabledForAll
};
explicit SystemProxyManager(PrefService* local_state);
SystemProxyManager(const SystemProxyManager&) = delete;
SystemProxyManager& operator=(const SystemProxyManager&) = delete;
~SystemProxyManager() override;
// Called by `ChromeBrowserMainPartsAsh` in order to bootstrap the
// SystemProxyManager instance after the required global data is
// available (local state, and CrosSettings).
static void Initialize(PrefService* local_state);
// Returns the instance of the SystemProxyManager singleton. May return
// nullptr during browser startup and shutdown. When calling Get(), either
// make sure that your code executes after browser startup and before shutdown
// or be careful to call Get() every time (instead of holding a pointer) and
// check for nullptr to handle cases where you might access
// SystemProxyManager during startup or shutdown.
static SystemProxyManager* Get();
// Called by `ChromeBrowserMainPartsAsh` in order to shutdown the
// SystemProxyManager instance before the required global data is destroyed
// (local state and CrosSettings).
static void Shutdown();
// If System-proxy is enabled, it returns the URL of the local proxy instance
// that authenticates system services, in PAC format, e.g.
// PROXY localhost:3128
// otherwise it returns an empty string.
std::string SystemServicesProxyPacString(
chromeos::SystemProxyOverride system_proxy_override) const;
void StartObservingPrimaryProfilePrefs(Profile* profile);
void StopObservingPrimaryProfilePrefs();
// If System-proxy is enabled, it will send a request via D-Bus to clear the
// user's proxy credentials cached by the local proxy workers. System-proxy
// requests proxy credentials from the browser by sending an
// |AuthenticationRequired| D-Bus signal.
void ClearUserCredentials();
// Enables/disables system-proxy and sets credentials to be used by ChromeOS
// system services when connecting to a remote web proxy via system-proxy. The
// credentials are only forwarded to system-proxy if the network proxy
// configuration is managed via policy. `auth_schemes` allows restricting the
// credentials to certain HTTP auth schemes.
void SetPolicySettings(bool system_proxy_enabled,
const std::string& system_services_username,
const std::string& system_services_password,
const std::vector<std::string>& auth_schemes);
void SetSystemProxyEnabledForTest(bool enabled);
void SetSystemServicesProxyUrlForTest(const std::string& local_proxy_url);
void SetSendAuthDetailsClosureForTest(base::RepeatingClosure closure);
RequestSystemProxyCredentialsView* GetActiveAuthDialogForTest();
void CloseAuthDialogForTest();
// Registers prefs stored in user profiles.
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Indicates whether the credentials set via the device policy
// SystemProxySettings can be used for proxy authentication in Chrome. The
// following conditions must be true:
// - the current session must be Managed Guest Session (MGS) or Kiosk app;
// - the proxy is set via policy;
// - System-proxy is enabled and credentials are set via policy;
// - `first_auth_attempt` is true;
// - `auth_info.scheme` must be allowed by the SystemProxySettings policy.
bool CanUsePolicyCredentials(const net::AuthChallengeInfo& auth_info,
bool first_auth_attempt);
// Returns a login delegate that posts `auth_required_callback` with the
// credentials provided by the policy SystemProxySettings. Callers must verify
// that `CanUsePolicyCredentials` is true before calling this method.
std::unique_ptr<content::LoginDelegate> CreateLoginDelegate(
content::LoginDelegate::LoginAuthRequiredCallback auth_required_callback);
private:
// NetworkStateHandlerObserver implementation
void DefaultNetworkChanged(const NetworkState* network) override;
// Called when the proxy configurations may have changed either by updates to
// the kProxy policy or updates to the default network.
void OnProxyConfigChanged();
// Returns true if there's a policy configured proxy on the default network
// (via device or user ONC policy, user policy or force installed extension).
bool IsManagedProxyConfigured();
// Returns true if the `kProxy` preference set by an extension can be changed
// by the user.
bool IsProxyConfiguredByUserViaExtension();
void OnSetAuthenticationDetails(
const system_proxy::SetAuthenticationDetailsResponse& response);
void OnShutDownProcess(const system_proxy::ShutDownResponse& response);
void OnClearUserCredentials(
const system_proxy::ClearUserCredentialsResponse& response);
void OnKerberosEnabledChanged();
void OnKerberosAccountChanged();
void OnArcEnabledChanged();
// Sets the value of the pref |kSystemProxyUserTrafficHostAndPort|.
void SetUserTrafficProxyPref(const std::string& user_traffic_address);
bool IsArcEnabled() const;
// Returns true if system-proxy is enabled by policy or flag.
bool IsEnabled() const;
// Sends the authentication details for |protection_space| to System-proxy via
// D-Bus.
void SendUserAuthenticationCredentials(
const system_proxy::ProtectionSpace& protection_space,
const std::string& username,
const std::string& password);
// Sends policy set credentials to System-proxy via D-Bus. Credentials are
// sent only if `username` and `password` are different than
// `last_sent_username_` and `last_sent_password_` or if `force_send` is true.
void SendPolicyAuthenticationCredentials(const std::string& username,
const std::string& password,
bool force_send);
// Send the Kerberos enabled state and active principal name to System-proxy
// via D-Bus.
void SendKerberosAuthenticationDetails();
// Sends empty credentials for |protection_space| to System-proxy via D-Bus.
// This can mean that a user is not signed into Chrome OS or they didn't
// provide proxy authentication credentials. In this case, System-proxy will
// forward the authentication failure (HTTP 407 status code) to the Chrome OS
// client.
void SendEmptyCredentials(
const system_proxy::ProtectionSpace& protection_space);
// Sends a shut-down command to the system-proxy daemon. Since system-proxy is
// started via dbus activation, if the daemon is inactive, this command will
// start the daemon and tell it to exit.
// TODO(crbug.com/1055245,acostinas): Do not send shut-down command if
// System-proxy is inactive.
void SendShutDownRequest(system_proxy::TrafficOrigin traffic);
// This function is called when the |WorkerActive| dbus signal is received.
void OnWorkerActive(const system_proxy::WorkerActiveSignalDetails& details);
// Requests from the NetworkService the user credentials associated with the
// protection space specified in |details|. This function is called when the
// |AuthenticationRequired| dbus signal is received.
void OnAuthenticationRequired(
const system_proxy::AuthenticationRequiredDetails& details);
// Forwards the user credentials to System-proxy. |credentials| may be empty
// indicating the credentials for the specified |protection_space| are not
// available.
void LookupProxyAuthCredentialsCallback(
const system_proxy::ProtectionSpace& protection_space,
const std::optional<net::AuthCredentials>& credentials);
void ShowAuthenticationNotification(
const system_proxy::ProtectionSpace& protection_space,
bool show_error);
// Shows a dialog which prompts the user to introduce proxy authentication
// credentials for OS level traffic. If |show_error_label| is true, the
// dialog will show a label that indicates the previous attempt to
// authenticate has failed due to invalid credentials.
void ShowAuthenticationDialog(
const system_proxy::ProtectionSpace& protection_space,
bool show_error_label);
void OnDialogAccepted(const system_proxy::ProtectionSpace& protection_space);
void OnDialogCanceled(const system_proxy::ProtectionSpace& protection_space);
void OnDialogClosed(const system_proxy::ProtectionSpace& protection_space);
// Closes the authentication notification or dialog if shown.
void CloseAuthenticationUI();
SystemProxyState system_proxy_state_ = SystemProxyState::kDisabled;
// The authority URI in the format host:port of the local proxy worker for
// system services.
std::string system_services_address_;
std::string system_services_username_;
std::string system_services_password_;
// List of proxy authentication schemes for which the policy set credentials
// can be used.
std::vector<std::string> policy_credentials_auth_schemes_;
// The credentials which were last sent to System-proxy. They can differ from
// `system_services_username_` and `system_services_username_` if the proxy
// configuration is not managed; in this case `last_sent_username_` and
// `last_sent_password_` are both empty even if credentials were specified by
// policy.
std::string last_sent_username_;
std::string last_sent_password_;
// Local state prefs, not owned.
raw_ptr<PrefService> local_state_ = nullptr;
// Notification which informs the user that System-proxy requires credentials
// for authentication to the remote proxy.
std::unique_ptr<SystemProxyNotification> notification_handler_;
// Owned by |auth_widget_|.
raw_ptr<RequestSystemProxyCredentialsView> active_auth_dialog_ = nullptr;
// Owned by the UI code (NativeWidget).
raw_ptr<views::Widget> auth_widget_ = nullptr;
// Primary profile, not owned.
raw_ptr<Profile> primary_profile_ = nullptr;
std::unique_ptr<extensions::PrefsUtil> extension_prefs_util_;
// Observer for Kerberos-related prefs.
std::unique_ptr<PrefChangeRegistrar> local_state_pref_change_registrar_;
std::unique_ptr<PrefChangeRegistrar> profile_pref_change_registrar_;
base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver>
network_state_handler_observer_{this};
base::RepeatingClosure send_auth_details_closure_for_test_;
base::WeakPtrFactory<SystemProxyManager> weak_factory_{this};
};
} // namespace ash
#endif // CHROME_BROWSER_ASH_NET_SYSTEM_PROXY_MANAGER_H_