[remoting corp logging] Implement CorpHostStatusLogger
This CL implements the CorpHostStatusLogger and hooks it up with the JingleSessionManager, so that it reports the disconnect event to the corp logging service with both the error code and the SessionAuthz reauth token attached. The tricky part of this CL is to pass the reauth token from the SessionAuthzReauthorizer to the CorpHostStatusLogger. There is `HostStatusObserver`, but it implements a mojo interface, meaning it will be rather difficult to pass pointers around (without being rejected by the mojo reviewer). Just passing the reauth token around in callbacks would also work, but that would be very messy. To get that working, this CL introduces a `SessionObserver`, which allows implementations to observer state changes on multiple sessions and know which session has changed. `authentication_type()` and `implementing_authenticator()` are added to `Authenticator` to allow `CorpHostStatusLogger` to extract the reauth token from the generalized `Authenticator` reference. Bug: b/328138087 Change-Id: Ic7b9ea297d28488ef65d4071860836b47e9c3b5d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5359454 Auto-Submit: Yuwei Huang <yuweih@chromium.org> Reviewed-by: Joe Downing <joedow@chromium.org> Commit-Queue: Yuwei Huang <yuweih@chromium.org> Cr-Commit-Position: refs/heads/main@{#1271835}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
1e8168a564
commit
73563374d5
remoting
base
host
BUILD.gncorp_host_status_logger.cccorp_host_status_logger.hcorp_host_status_logger_unittest.ccpam_authorization_factory_posix.ccremoting_me2me_host.cc
proto
protocol
BUILD.gnauthenticator.hcredentials_type.hfake_authenticator.ccfake_authenticator.hfake_session.ccfake_session.hjingle_session.ccjingle_session.hjingle_session_manager.ccjingle_session_manager.hjingle_session_unittest.ccnegotiating_authenticator_base.ccnegotiating_authenticator_base.hnegotiating_authenticator_unittest.ccnegotiating_host_authenticator.ccpairing_authenticator_base.ccpairing_authenticator_base.hprotocol_mock_objects.ccprotocol_mock_objects.hrejecting_authenticator.ccrejecting_authenticator.hsession.hsession_authz_authenticator.ccsession_authz_authenticator.hsession_authz_authenticator_unittest.ccsession_authz_reauthorizer.hsession_manager.hsession_observer.hspake2_authenticator.ccspake2_authenticator.hthird_party_authenticator_base.ccthird_party_authenticator_base.hvalidating_authenticator.ccvalidating_authenticator.h
@ -43,6 +43,8 @@ source_set("base") {
|
||||
"compound_buffer.h",
|
||||
"constants.cc",
|
||||
"constants.h",
|
||||
"corp_auth_util.cc",
|
||||
"corp_auth_util.h",
|
||||
"corp_logging_service_client.cc",
|
||||
"corp_logging_service_client.h",
|
||||
"corp_service_client.cc",
|
||||
|
35
remoting/base/corp_auth_util.cc
Normal file
35
remoting/base/corp_auth_util.cc
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "remoting/base/corp_auth_util.h"
|
||||
|
||||
#include "base/check.h"
|
||||
#include "remoting/base/oauth_token_getter_impl.h"
|
||||
|
||||
namespace remoting {
|
||||
namespace {
|
||||
|
||||
constexpr char kOAuthScope[] =
|
||||
"https://www.googleapis.com/auth/chromoting.me2me.host";
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<OAuthTokenGetterImpl> CreateCorpTokenGetter(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
||||
const std::string& service_account_email,
|
||||
const std::string& refresh_token) {
|
||||
DCHECK(url_loader_factory);
|
||||
DCHECK(!service_account_email.empty());
|
||||
DCHECK(!refresh_token.empty());
|
||||
|
||||
return std::make_unique<OAuthTokenGetterImpl>(
|
||||
std::make_unique<OAuthTokenGetter::OAuthAuthorizationCredentials>(
|
||||
service_account_email, refresh_token,
|
||||
/* is_service_account= */ true,
|
||||
std::vector<std::string>{kOAuthScope}),
|
||||
url_loader_factory,
|
||||
/* auto_refresh= */ false);
|
||||
}
|
||||
|
||||
} // namespace remoting
|
28
remoting/base/corp_auth_util.h
Normal file
28
remoting/base/corp_auth_util.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef REMOTING_BASE_CORP_AUTH_UTIL_H_
|
||||
#define REMOTING_BASE_CORP_AUTH_UTIL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "remoting/base/oauth_token_getter_impl.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
|
||||
namespace remoting {
|
||||
|
||||
// Creates an OAuthTokenGetterImpl that is suitable for making requests to corp
|
||||
// APIs. Corp APIs' authentication config is different from that of the regular
|
||||
// APIs, so you can't make authenticated corp API requests with the regular
|
||||
// OAuthTokenGetter.
|
||||
std::unique_ptr<OAuthTokenGetterImpl> CreateCorpTokenGetter(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
||||
const std::string& service_account_email,
|
||||
const std::string& refresh_token);
|
||||
|
||||
} // namespace remoting
|
||||
|
||||
#endif // REMOTING_BASE_CORP_AUTH_UTIL_H_
|
@ -9,34 +9,22 @@
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "remoting/base/corp_auth_util.h"
|
||||
#include "remoting/base/corp_session_authz_service_client.h"
|
||||
#include "remoting/base/oauth_token_getter_impl.h"
|
||||
#include "remoting/base/oauth_token_getter_proxy.h"
|
||||
|
||||
namespace remoting {
|
||||
namespace {
|
||||
|
||||
constexpr char kOAuthScope[] =
|
||||
"https://www.googleapis.com/auth/chromoting.me2me.host";
|
||||
|
||||
} // namespace
|
||||
|
||||
CorpSessionAuthzServiceClientFactory::CorpSessionAuthzServiceClientFactory(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
||||
const std::string& service_account_email,
|
||||
const std::string& refresh_token) {
|
||||
DCHECK(url_loader_factory);
|
||||
DCHECK(!service_account_email.empty());
|
||||
DCHECK(!refresh_token.empty());
|
||||
|
||||
url_loader_factory_ = url_loader_factory;
|
||||
oauth_token_getter_ = std::make_unique<OAuthTokenGetterImpl>(
|
||||
std::make_unique<OAuthTokenGetter::OAuthAuthorizationCredentials>(
|
||||
service_account_email, refresh_token,
|
||||
/* is_service_account= */ true,
|
||||
std::vector<std::string>{kOAuthScope}),
|
||||
url_loader_factory_,
|
||||
/* auto_refresh= */ false);
|
||||
oauth_token_getter_ = CreateCorpTokenGetter(
|
||||
url_loader_factory, service_account_email, refresh_token);
|
||||
oauth_token_getter_task_runner_ =
|
||||
base::SequencedTaskRunner::GetCurrentDefault();
|
||||
}
|
||||
|
@ -275,6 +275,8 @@ static_library("common") {
|
||||
"config_watcher.h",
|
||||
"continue_window.cc",
|
||||
"continue_window.h",
|
||||
"corp_host_status_logger.cc",
|
||||
"corp_host_status_logger.h",
|
||||
"crash_process.cc",
|
||||
"crash_process.h",
|
||||
"curtain_mode.h",
|
||||
@ -795,6 +797,7 @@ source_set("unit_tests") {
|
||||
"chromoting_host_unittest.cc",
|
||||
"client_session_unittest.cc",
|
||||
"config_file_watcher_unittest.cc",
|
||||
"corp_host_status_logger_unittest.cc",
|
||||
"daemon_process_unittest.cc",
|
||||
"desktop_display_info_unittest.cc",
|
||||
"desktop_display_layout_util_unittest.cc",
|
||||
@ -867,6 +870,7 @@ source_set("unit_tests") {
|
||||
"//remoting/host/setup:common",
|
||||
"//remoting/host/webauthn:unit_tests",
|
||||
"//remoting/proto",
|
||||
"//remoting/proto:internal_structs",
|
||||
"//remoting/proto/remoting/v1:chrome_os_enterprise_options",
|
||||
"//remoting/proto/remoting/v1:remote_support_host_messages",
|
||||
"//remoting/protocol:test_support",
|
||||
|
86
remoting/host/corp_host_status_logger.cc
Normal file
86
remoting/host/corp_host_status_logger.cc
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "remoting/host/corp_host_status_logger.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "remoting/base/corp_auth_util.h"
|
||||
#include "remoting/base/corp_logging_service_client.h"
|
||||
#include "remoting/base/logging.h"
|
||||
#include "remoting/base/protobuf_http_status.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/session.h"
|
||||
#include "remoting/protocol/session_authz_authenticator.h"
|
||||
#include "remoting/protocol/session_authz_reauthorizer.h"
|
||||
#include "remoting/protocol/session_manager.h"
|
||||
|
||||
namespace remoting {
|
||||
|
||||
CorpHostStatusLogger::CorpHostStatusLogger(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
||||
const std::string& service_account_email,
|
||||
const std::string& refresh_token)
|
||||
: CorpHostStatusLogger(std::make_unique<CorpLoggingServiceClient>(
|
||||
url_loader_factory,
|
||||
CreateCorpTokenGetter(url_loader_factory,
|
||||
service_account_email,
|
||||
refresh_token))) {}
|
||||
|
||||
CorpHostStatusLogger::CorpHostStatusLogger(
|
||||
std::unique_ptr<LoggingServiceClient> service_client)
|
||||
: service_client_(std::move(service_client)) {}
|
||||
|
||||
CorpHostStatusLogger::~CorpHostStatusLogger() = default;
|
||||
|
||||
void CorpHostStatusLogger::StartObserving(
|
||||
protocol::SessionManager& session_manager) {
|
||||
observer_subscription_ = session_manager.AddSessionObserver(this);
|
||||
}
|
||||
|
||||
void CorpHostStatusLogger::OnSessionStateChange(
|
||||
const protocol::Session& session,
|
||||
protocol::Session::State state) {
|
||||
if (state != protocol::Session::State::CLOSED &&
|
||||
state != protocol::Session::State::FAILED) {
|
||||
return;
|
||||
}
|
||||
if (session.authenticator().credentials_type() !=
|
||||
protocol::CredentialsType::CORP_SESSION_AUTHZ) {
|
||||
VLOG(1) << "Current session is not authenticated with SessionAuthz. "
|
||||
<< "Disconnect event not logged.";
|
||||
return;
|
||||
}
|
||||
const protocol::SessionAuthzReauthorizer* reauthorizer =
|
||||
static_cast<const protocol::SessionAuthzAuthenticator&>(
|
||||
session.authenticator().implementing_authenticator())
|
||||
.reauthorizer();
|
||||
if (!reauthorizer) {
|
||||
// TODO: b/328138087 - add |session_authz_id| to the request so that we can
|
||||
// still log the disconnect event explicitly, in case SessionAuthz has
|
||||
// failed.
|
||||
LOG(WARNING) << "Current session does not have a reauthorizer. "
|
||||
<< "Disconnect event not logged.";
|
||||
return;
|
||||
}
|
||||
internal::ReportSessionDisconnectedRequestStruct request{
|
||||
.session_authz_reauth_token = reauthorizer->session_reauth_token(),
|
||||
.error_code = session.error(),
|
||||
};
|
||||
service_client_->ReportSessionDisconnected(
|
||||
request, base::BindOnce([](const ProtobufHttpStatus& status) {
|
||||
if (status.ok()) {
|
||||
HOST_LOG << "Disconnect event logged.";
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to log disconnect event: "
|
||||
<< status.error_message() << '('
|
||||
<< static_cast<int>(status.error_code()) << ')';
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace remoting
|
51
remoting/host/corp_host_status_logger.h
Normal file
51
remoting/host/corp_host_status_logger.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef REMOTING_HOST_CORP_HOST_STATUS_LOGGER_H_
|
||||
#define REMOTING_HOST_CORP_HOST_STATUS_LOGGER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "remoting/protocol/session.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
|
||||
namespace remoting {
|
||||
namespace protocol {
|
||||
class SessionManager;
|
||||
} // namespace protocol
|
||||
|
||||
class LoggingServiceClient;
|
||||
|
||||
// A class that reports host status changes to the corp logging service. This is
|
||||
// not used for external users. For internal details, see go/crd-corp-logging.
|
||||
class CorpHostStatusLogger final : public protocol::SessionObserver {
|
||||
public:
|
||||
CorpHostStatusLogger(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
||||
const std::string& service_account_email,
|
||||
const std::string& refresh_token);
|
||||
explicit CorpHostStatusLogger(
|
||||
std::unique_ptr<LoggingServiceClient> service_client);
|
||||
~CorpHostStatusLogger() override;
|
||||
CorpHostStatusLogger(const CorpHostStatusLogger&) = delete;
|
||||
CorpHostStatusLogger& operator=(const CorpHostStatusLogger&) = delete;
|
||||
|
||||
void StartObserving(protocol::SessionManager& session_manager);
|
||||
|
||||
private:
|
||||
// protocol::SessionObserver
|
||||
void OnSessionStateChange(const protocol::Session& session,
|
||||
protocol::Session::State state) override;
|
||||
|
||||
std::unique_ptr<LoggingServiceClient> service_client_;
|
||||
Subscription observer_subscription_;
|
||||
};
|
||||
|
||||
} // namespace remoting
|
||||
|
||||
#endif // REMOTING_HOST_CORP_HOST_STATUS_LOGGER_H_
|
158
remoting/host/corp_host_status_logger_unittest.cc
Normal file
158
remoting/host/corp_host_status_logger_unittest.cc
Normal file
@ -0,0 +1,158 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "remoting/host/corp_host_status_logger.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/test/mock_callback.h"
|
||||
#include "base/time/time.h"
|
||||
#include "remoting/base/logging_service_client.h"
|
||||
#include "remoting/proto/logging_service.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/protocol_mock_objects.h"
|
||||
#include "remoting/protocol/session_authz_authenticator.h"
|
||||
#include "remoting/protocol/session_authz_reauthorizer.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace remoting {
|
||||
namespace {
|
||||
|
||||
using testing::_;
|
||||
using testing::Return;
|
||||
using testing::ReturnRef;
|
||||
|
||||
constexpr char kFakeReauthToken[] = "fake_reauth_token";
|
||||
|
||||
class MockLoggingServiceClient final : public LoggingServiceClient {
|
||||
public:
|
||||
MockLoggingServiceClient() = default;
|
||||
~MockLoggingServiceClient() override = default;
|
||||
|
||||
MockLoggingServiceClient(const MockLoggingServiceClient&) = delete;
|
||||
MockLoggingServiceClient& operator=(const MockLoggingServiceClient&) = delete;
|
||||
|
||||
MOCK_METHOD(void,
|
||||
ReportSessionDisconnected,
|
||||
(const internal::ReportSessionDisconnectedRequestStruct&,
|
||||
StatusCallback));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class CorpHostStatusLoggerTest : public testing::Test {
|
||||
public:
|
||||
CorpHostStatusLoggerTest();
|
||||
~CorpHostStatusLoggerTest() override;
|
||||
|
||||
protected:
|
||||
void SetUpSessionAuthzAuthenticator(bool has_reauthorizer);
|
||||
|
||||
raw_ptr<MockLoggingServiceClient> service_client_;
|
||||
std::unique_ptr<CorpHostStatusLogger> logger_;
|
||||
raw_ptr<protocol::SessionObserver> logger_as_observer_;
|
||||
base::MockOnceClosure unsubscribe_closure_;
|
||||
protocol::MockSession session_;
|
||||
protocol::MockSessionManager session_manager_;
|
||||
protocol::MockAuthenticator authenticator_;
|
||||
protocol::SessionAuthzAuthenticator session_authz_authenticator_{
|
||||
protocol::CredentialsType::CORP_SESSION_AUTHZ, nullptr,
|
||||
base::NullCallback()};
|
||||
};
|
||||
|
||||
CorpHostStatusLoggerTest::CorpHostStatusLoggerTest() {
|
||||
auto service_client = std::make_unique<MockLoggingServiceClient>();
|
||||
service_client_ = service_client.get();
|
||||
logger_ = std::make_unique<CorpHostStatusLogger>(std::move(service_client));
|
||||
logger_as_observer_ = logger_.get();
|
||||
|
||||
EXPECT_CALL(session_, authenticator())
|
||||
.WillRepeatedly(ReturnRef(authenticator_));
|
||||
EXPECT_CALL(session_manager_, AddSessionObserver(logger_.get()))
|
||||
.WillOnce(Return(
|
||||
protocol::SessionObserver::Subscription(unsubscribe_closure_.Get())));
|
||||
logger_->StartObserving(session_manager_);
|
||||
}
|
||||
|
||||
CorpHostStatusLoggerTest::~CorpHostStatusLoggerTest() {
|
||||
EXPECT_CALL(unsubscribe_closure_, Run());
|
||||
service_client_ = nullptr;
|
||||
logger_as_observer_ = nullptr;
|
||||
logger_.reset();
|
||||
}
|
||||
|
||||
void CorpHostStatusLoggerTest::SetUpSessionAuthzAuthenticator(
|
||||
bool has_reauthorizer) {
|
||||
EXPECT_CALL(authenticator_, credentials_type())
|
||||
.WillOnce(Return(session_authz_authenticator_.credentials_type()));
|
||||
EXPECT_CALL(authenticator_, implementing_authenticator())
|
||||
.WillOnce(
|
||||
ReturnRef(session_authz_authenticator_.implementing_authenticator()));
|
||||
if (has_reauthorizer) {
|
||||
session_authz_authenticator_.SetReauthorizerForTesting(
|
||||
std::make_unique<protocol::SessionAuthzReauthorizer>(
|
||||
nullptr, "fake_session_id", kFakeReauthToken, base::Minutes(5),
|
||||
base::DoNothing()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, UnsubscribeOnceDestroyed) {
|
||||
// Test done in the destructor.
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, IgnoreUninterestingState) {
|
||||
EXPECT_CALL(*service_client_, ReportSessionDisconnected(_, _)).Times(0);
|
||||
|
||||
logger_as_observer_->OnSessionStateChange(
|
||||
session_, protocol::Session::State::AUTHENTICATING);
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, IgnoreNonSessionAuthzSession) {
|
||||
EXPECT_CALL(*service_client_, ReportSessionDisconnected(_, _)).Times(0);
|
||||
EXPECT_CALL(authenticator_, credentials_type())
|
||||
.WillOnce(Return(protocol::CredentialsType::SHARED_SECRET));
|
||||
|
||||
logger_as_observer_->OnSessionStateChange(session_,
|
||||
protocol::Session::State::CLOSED);
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, IgnoreSessionWithoutReauthorizer) {
|
||||
EXPECT_CALL(*service_client_, ReportSessionDisconnected(_, _)).Times(0);
|
||||
SetUpSessionAuthzAuthenticator(/* has_reauthorizer= */ false);
|
||||
|
||||
logger_as_observer_->OnSessionStateChange(session_,
|
||||
protocol::Session::State::CLOSED);
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, ReportsSessionDisconnectedForClosed) {
|
||||
EXPECT_CALL(session_, error()).WillOnce(Return(ErrorCode::OK));
|
||||
internal::ReportSessionDisconnectedRequestStruct expected_request{
|
||||
.session_authz_reauth_token = kFakeReauthToken,
|
||||
.error_code = ErrorCode::OK,
|
||||
};
|
||||
EXPECT_CALL(*service_client_, ReportSessionDisconnected(expected_request, _));
|
||||
SetUpSessionAuthzAuthenticator(/* has_reauthorizer= */ true);
|
||||
|
||||
logger_as_observer_->OnSessionStateChange(session_,
|
||||
protocol::Session::State::CLOSED);
|
||||
}
|
||||
|
||||
TEST_F(CorpHostStatusLoggerTest, ReportsSessionDisconnectedForFailed) {
|
||||
EXPECT_CALL(session_, error()).WillOnce(Return(ErrorCode::PEER_IS_OFFLINE));
|
||||
internal::ReportSessionDisconnectedRequestStruct expected_request{
|
||||
.session_authz_reauth_token = kFakeReauthToken,
|
||||
.error_code = ErrorCode::PEER_IS_OFFLINE,
|
||||
};
|
||||
EXPECT_CALL(*service_client_, ReportSessionDisconnected(expected_request, _));
|
||||
SetUpSessionAuthzAuthenticator(/* has_reauthorizer= */ true);
|
||||
|
||||
logger_as_observer_->OnSessionStateChange(session_,
|
||||
protocol::Session::State::FAILED);
|
||||
}
|
||||
|
||||
} // namespace remoting
|
@ -25,6 +25,8 @@ class PamAuthorizer : public protocol::Authenticator {
|
||||
~PamAuthorizer() override;
|
||||
|
||||
// protocol::Authenticator:
|
||||
protocol::CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
@ -59,6 +61,15 @@ PamAuthorizer::PamAuthorizer(
|
||||
|
||||
PamAuthorizer::~PamAuthorizer() {}
|
||||
|
||||
protocol::CredentialsType PamAuthorizer::credentials_type() const {
|
||||
return underlying_->credentials_type();
|
||||
}
|
||||
|
||||
const protocol::Authenticator& PamAuthorizer::implementing_authenticator()
|
||||
const {
|
||||
return underlying_->implementing_authenticator();
|
||||
}
|
||||
|
||||
protocol::Authenticator::State PamAuthorizer::state() const {
|
||||
if (local_login_status_ == DISALLOWED) {
|
||||
return REJECTED;
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "remoting/host/chromoting_host_context.h"
|
||||
#include "remoting/host/config_file_watcher.h"
|
||||
#include "remoting/host/config_watcher.h"
|
||||
#include "remoting/host/corp_host_status_logger.h"
|
||||
#include "remoting/host/crash_process.h"
|
||||
#include "remoting/host/desktop_environment.h"
|
||||
#include "remoting/host/desktop_session_connector.h"
|
||||
@ -475,6 +476,9 @@ class HostProcess : public ConfigWatcher::Delegate,
|
||||
#endif
|
||||
std::unique_ptr<HostPowerSaveBlocker> power_save_blocker_;
|
||||
|
||||
// Only set if |is_googler_| is true.
|
||||
std::unique_ptr<CorpHostStatusLogger> corp_host_status_logger_;
|
||||
|
||||
std::unique_ptr<ChromotingHost> host_;
|
||||
|
||||
// Used to keep this HostProcess alive until it is shutdown.
|
||||
@ -1872,6 +1876,10 @@ void HostProcess::StartHost() {
|
||||
// externally, we don't want to apply this policy for non-Googlers.
|
||||
desktop_environment_options_.set_enable_user_interface(
|
||||
enable_user_interface_);
|
||||
corp_host_status_logger_ = std::make_unique<CorpHostStatusLogger>(
|
||||
context_->url_loader_factory(), service_account_email_,
|
||||
oauth_refresh_token_);
|
||||
corp_host_status_logger_->StartObserving(*session_manager);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)
|
||||
@ -2002,6 +2010,7 @@ void HostProcess::GoOffline(const std::string& host_offline_reason) {
|
||||
host_event_logger_.reset();
|
||||
host_status_logger_.reset();
|
||||
power_save_blocker_.reset();
|
||||
corp_host_status_logger_.reset();
|
||||
ftl_host_change_notification_listener_.reset();
|
||||
|
||||
// Before shutting down HostSignalingManager, send the |host_offline_reason|
|
||||
|
@ -12,6 +12,9 @@
|
||||
namespace remoting::internal {
|
||||
|
||||
struct ReportSessionDisconnectedRequestStruct {
|
||||
bool operator==(const ReportSessionDisconnectedRequestStruct&) const =
|
||||
default;
|
||||
|
||||
std::string session_authz_reauth_token;
|
||||
ErrorCode error_code;
|
||||
};
|
||||
|
@ -70,6 +70,7 @@ static_library("protocol") {
|
||||
"connection_to_host.h",
|
||||
"content_description.cc",
|
||||
"content_description.h",
|
||||
"credentials_type.h",
|
||||
"data_channel_manager.cc",
|
||||
"data_channel_manager.h",
|
||||
"datagram_channel_factory.h",
|
||||
@ -180,6 +181,7 @@ static_library("protocol") {
|
||||
"session_authz_reauthorizer.cc",
|
||||
"session_authz_reauthorizer.h",
|
||||
"session_manager.h",
|
||||
"session_observer.h",
|
||||
"session_options_provider.h",
|
||||
"session_plugin.h",
|
||||
"socket_util.cc",
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
|
||||
namespace jingle_xmpp {
|
||||
class XmlElement;
|
||||
@ -118,6 +119,17 @@ class Authenticator {
|
||||
Authenticator();
|
||||
virtual ~Authenticator();
|
||||
|
||||
// Returns the credentials type of the authenticator.
|
||||
virtual CredentialsType credentials_type() const = 0;
|
||||
|
||||
// Returns the authenticator that implements `credentials_type()`. The
|
||||
// returned value is usually `*this`, but may be an underlying authenticator
|
||||
// if this authenticator is a wrapper (e.g. negotiating) authenticator. Note
|
||||
// that some authenticators may use other authenticators internally, but they
|
||||
// will still return `*this` as long as it implements an credentials type
|
||||
// that is not implemented by the authenticators it use.
|
||||
virtual const Authenticator& implementing_authenticator() const = 0;
|
||||
|
||||
// Returns current state of the authenticator.
|
||||
virtual State state() const = 0;
|
||||
|
||||
|
34
remoting/protocol/credentials_type.h
Normal file
34
remoting/protocol/credentials_type.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef REMOTING_PROTOCOL_CREDENTIALS_TYPE_H_
|
||||
#define REMOTING_PROTOCOL_CREDENTIALS_TYPE_H_
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
// The type of the credentials used for authentication.
|
||||
enum class CredentialsType {
|
||||
// The credentials type is unknown. This is usually reported by a wrapper
|
||||
// (e.g. negotiating) authenticator when the underlying authenticator is not
|
||||
// determined yet.
|
||||
UNKNOWN,
|
||||
|
||||
// Key exchange based on a shared secret, e.g. a PIN or an IT2ME access code.
|
||||
SHARED_SECRET,
|
||||
|
||||
// Key exchange based on a shared pairing secret.
|
||||
PAIRED,
|
||||
|
||||
// Authentication using the third-party authentication server, which generates
|
||||
// a shared secret for key exchange.
|
||||
THIRD_PARTY,
|
||||
|
||||
// Authentication using the corp-internal SessionAuthz service, which
|
||||
// generates a shared secret for key exchange.
|
||||
CORP_SESSION_AUTHZ,
|
||||
};
|
||||
|
||||
} // namespace remoting::protocol
|
||||
|
||||
#endif // REMOTING_PROTOCOL_CREDENTIALS_TYPE_H_
|
@ -122,6 +122,14 @@ void FakeAuthenticator::Resume() {
|
||||
std::move(resume_closure_).Run();
|
||||
}
|
||||
|
||||
CredentialsType FakeAuthenticator::credentials_type() const {
|
||||
return config_.credentials_type;
|
||||
}
|
||||
|
||||
const Authenticator& FakeAuthenticator::implementing_authenticator() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State FakeAuthenticator::state() const {
|
||||
EXPECT_LE(messages_, config_.round_trips * 2);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
@ -63,6 +64,7 @@ class FakeAuthenticator : public Authenticator {
|
||||
Action action = Action::ACCEPT;
|
||||
bool async = true;
|
||||
raw_ptr<base::RepeatingClosureList> reject_after_accepted;
|
||||
CredentialsType credentials_type = CredentialsType::SHARED_SECRET;
|
||||
};
|
||||
|
||||
FakeAuthenticator(Type type,
|
||||
@ -96,6 +98,8 @@ class FakeAuthenticator : public Authenticator {
|
||||
void Resume();
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/location.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/fake_authenticator.h"
|
||||
#include "remoting/protocol/session_plugin.h"
|
||||
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
|
||||
@ -58,7 +59,7 @@ void FakeSession::SetEventHandler(EventHandler* event_handler) {
|
||||
event_handler_ = event_handler;
|
||||
}
|
||||
|
||||
ErrorCode FakeSession::error() {
|
||||
ErrorCode FakeSession::error() const {
|
||||
return error_;
|
||||
}
|
||||
|
||||
@ -70,6 +71,10 @@ const SessionConfig& FakeSession::config() {
|
||||
return *config_;
|
||||
}
|
||||
|
||||
const Authenticator& FakeSession::authenticator() const {
|
||||
return *authenticator_;
|
||||
}
|
||||
|
||||
void FakeSession::SetTransport(Transport* transport) {
|
||||
transport_ = transport;
|
||||
}
|
||||
|
@ -51,9 +51,10 @@ class FakeSession : public Session {
|
||||
|
||||
// Session interface.
|
||||
void SetEventHandler(EventHandler* event_handler) override;
|
||||
ErrorCode error() override;
|
||||
ErrorCode error() const override;
|
||||
const std::string& jid() override;
|
||||
const SessionConfig& config() override;
|
||||
const Authenticator& authenticator() const override;
|
||||
void SetTransport(Transport* transport) override;
|
||||
void Close(ErrorCode error) override;
|
||||
void AddPlugin(SessionPlugin* plugin) override;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "remoting/protocol/jingle_messages.h"
|
||||
#include "remoting/protocol/jingle_session_manager.h"
|
||||
#include "remoting/protocol/session_config.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "remoting/protocol/session_plugin.h"
|
||||
#include "remoting/protocol/transport.h"
|
||||
#include "remoting/signaling/iq_sender.h"
|
||||
@ -214,7 +215,7 @@ void JingleSession::SetEventHandler(Session::EventHandler* event_handler) {
|
||||
event_handler_ = event_handler;
|
||||
}
|
||||
|
||||
ErrorCode JingleSession::error() {
|
||||
ErrorCode JingleSession::error() const {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return error_;
|
||||
}
|
||||
@ -343,6 +344,11 @@ const SessionConfig& JingleSession::config() {
|
||||
return *config_;
|
||||
}
|
||||
|
||||
const Authenticator& JingleSession::authenticator() const {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
return *authenticator_;
|
||||
}
|
||||
|
||||
void JingleSession::SetTransport(Transport* transport) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
DCHECK(!transport_);
|
||||
@ -800,6 +806,11 @@ void JingleSession::SetState(State new_state) {
|
||||
DCHECK_NE(state_, FAILED);
|
||||
|
||||
state_ = new_state;
|
||||
// Observers must be called before the event handler, since the event
|
||||
// handler may destroy the session.
|
||||
for (SessionObserver& observer : session_manager_->observers_) {
|
||||
observer.OnSessionStateChange(*this, new_state);
|
||||
}
|
||||
if (event_handler_) {
|
||||
event_handler_->OnSessionStateChange(new_state);
|
||||
}
|
||||
|
@ -38,9 +38,10 @@ class JingleSession : public Session {
|
||||
|
||||
// Session interface.
|
||||
void SetEventHandler(Session::EventHandler* event_handler) override;
|
||||
ErrorCode error() override;
|
||||
ErrorCode error() const override;
|
||||
const std::string& jid() override;
|
||||
const SessionConfig& config() override;
|
||||
const Authenticator& authenticator() const override;
|
||||
void SetTransport(Transport* transport) override;
|
||||
void Close(protocol::ErrorCode error) override;
|
||||
void AddPlugin(SessionPlugin* plugin) override;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "remoting/protocol/content_description.h"
|
||||
#include "remoting/protocol/jingle_messages.h"
|
||||
#include "remoting/protocol/jingle_session.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "remoting/protocol/transport.h"
|
||||
#include "remoting/signaling/iq_sender.h"
|
||||
#include "remoting/signaling/signal_strategy.h"
|
||||
@ -59,6 +60,17 @@ void JingleSessionManager::set_authenticator_factory(
|
||||
authenticator_factory_ = std::move(authenticator_factory);
|
||||
}
|
||||
|
||||
SessionObserver::Subscription JingleSessionManager::AddSessionObserver(
|
||||
SessionObserver* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
return SessionObserver::Subscription(
|
||||
base::BindOnce(&JingleSessionManager::RemoveSessionObserver,
|
||||
weak_factory_.GetWeakPtr(), observer));
|
||||
}
|
||||
void JingleSessionManager::RemoveSessionObserver(SessionObserver* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void JingleSessionManager::OnSignalStrategyStateChange(
|
||||
SignalStrategy::State state) {}
|
||||
|
||||
|
@ -9,9 +9,12 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "remoting/protocol/jingle_messages.h"
|
||||
#include "remoting/protocol/session_manager.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "remoting/signaling/signal_strategy.h"
|
||||
|
||||
namespace jingle_xmpp {
|
||||
@ -50,10 +53,14 @@ class JingleSessionManager : public SessionManager,
|
||||
std::unique_ptr<Authenticator> authenticator) override;
|
||||
void set_authenticator_factory(
|
||||
std::unique_ptr<AuthenticatorFactory> authenticator_factory) override;
|
||||
[[nodiscard]] SessionObserver::Subscription AddSessionObserver(
|
||||
SessionObserver* observer) override;
|
||||
|
||||
private:
|
||||
friend class JingleSession;
|
||||
|
||||
void RemoveSessionObserver(SessionObserver* observer);
|
||||
|
||||
// SignalStrategy::Listener interface.
|
||||
void OnSignalStrategyStateChange(SignalStrategy::State state) override;
|
||||
bool OnSignalStrategyIncomingStanza(
|
||||
@ -76,8 +83,11 @@ class JingleSessionManager : public SessionManager,
|
||||
std::unique_ptr<IqSender> iq_sender_;
|
||||
|
||||
SessionsMap sessions_;
|
||||
base::ObserverList<SessionObserver> observers_;
|
||||
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
|
||||
base::WeakPtrFactory<JingleSessionManager> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "remoting/protocol/fake_authenticator.h"
|
||||
#include "remoting/protocol/jingle_session_manager.h"
|
||||
#include "remoting/protocol/network_settings.h"
|
||||
#include "remoting/protocol/protocol_mock_objects.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "remoting/protocol/session_plugin.h"
|
||||
#include "remoting/protocol/transport.h"
|
||||
#include "remoting/protocol/transport_context.h"
|
||||
@ -663,4 +665,34 @@ TEST_F(JingleSessionTest, AuthenticatorRejectedAfterAccepted) {
|
||||
ASSERT_NE(client_session_->error(), ErrorCode::OK);
|
||||
}
|
||||
|
||||
TEST_F(JingleSessionTest, ObserverIsNotified) {
|
||||
MockSessionObserver observer;
|
||||
const Session* accepted_session = nullptr;
|
||||
EXPECT_CALL(observer, OnSessionStateChange(_, _))
|
||||
.WillRepeatedly([&](const Session& session, Session::State state) {
|
||||
if (state == Session::State::ACCEPTED) {
|
||||
accepted_session = &session;
|
||||
}
|
||||
});
|
||||
FakeAuthenticator::Config auth_config(FakeAuthenticator::ACCEPT);
|
||||
|
||||
CreateSessionManagers(auth_config);
|
||||
auto subscription = host_server_->AddSessionObserver(&observer);
|
||||
InitiateConnection(auth_config, false);
|
||||
|
||||
ASSERT_EQ(accepted_session, host_session_.get());
|
||||
}
|
||||
|
||||
TEST_F(JingleSessionTest, ObserverIsNotNotifiedAfterSubscriptionIsDestroyed) {
|
||||
MockSessionObserver observer;
|
||||
EXPECT_CALL(observer, OnSessionStateChange(_, _)).Times(0);
|
||||
FakeAuthenticator::Config auth_config(FakeAuthenticator::ACCEPT);
|
||||
|
||||
CreateSessionManagers(auth_config);
|
||||
auto subscription = std::make_unique<SessionObserver::Subscription>(
|
||||
host_server_->AddSessionObserver(&observer));
|
||||
subscription.reset();
|
||||
InitiateConnection(auth_config, false);
|
||||
}
|
||||
|
||||
} // namespace remoting::protocol
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "remoting/base/rsa_key_pair.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
|
||||
|
||||
namespace remoting::protocol {
|
||||
@ -38,6 +39,20 @@ NegotiatingAuthenticatorBase::NegotiatingAuthenticatorBase(
|
||||
|
||||
NegotiatingAuthenticatorBase::~NegotiatingAuthenticatorBase() = default;
|
||||
|
||||
CredentialsType NegotiatingAuthenticatorBase::credentials_type() const {
|
||||
if (!current_authenticator_) {
|
||||
return CredentialsType::UNKNOWN;
|
||||
}
|
||||
return current_authenticator_->credentials_type();
|
||||
}
|
||||
|
||||
const Authenticator& NegotiatingAuthenticatorBase::implementing_authenticator()
|
||||
const {
|
||||
return current_authenticator_
|
||||
? current_authenticator_->implementing_authenticator()
|
||||
: *this;
|
||||
}
|
||||
|
||||
Authenticator::State NegotiatingAuthenticatorBase::state() const {
|
||||
return state_;
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ class NegotiatingAuthenticatorBase : public Authenticator {
|
||||
~NegotiatingAuthenticatorBase() override;
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "remoting/protocol/authenticator_test_base.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/connection_tester.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/host_authentication_config.h"
|
||||
#include "remoting/protocol/negotiating_authenticator_base.h"
|
||||
#include "remoting/protocol/negotiating_client_authenticator.h"
|
||||
@ -325,4 +326,15 @@ TEST_F(NegotiatingAuthenticatorTest, NotifyStateChangeAfterAccepted) {
|
||||
Authenticator::RejectionReason::REAUTHZ_POLICY_CHECK_FAILED);
|
||||
}
|
||||
|
||||
TEST_F(NegotiatingAuthenticatorTest,
|
||||
ReturnCorrectCredentialsTypeAndImplementingAuthenticator) {
|
||||
InitAuthenticators(kNoClientId, kNoPairedSecret, kTestPin, kTestPin);
|
||||
|
||||
ASSERT_EQ(host_->credentials_type(), CredentialsType::UNKNOWN);
|
||||
ASSERT_EQ(&host_->implementing_authenticator(), host_.get());
|
||||
VerifyAccepted();
|
||||
ASSERT_EQ(host_->credentials_type(), CredentialsType::SHARED_SECRET);
|
||||
ASSERT_NE(&host_->implementing_authenticator(), host_.get());
|
||||
}
|
||||
|
||||
} // namespace remoting::protocol
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "base/strings/string_split.h"
|
||||
#include "remoting/base/rsa_key_pair.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/host_authentication_config.h"
|
||||
#include "remoting/protocol/pairing_host_authenticator.h"
|
||||
#include "remoting/protocol/pairing_registry.h"
|
||||
@ -149,6 +150,7 @@ void NegotiatingHostAuthenticator::CreateAuthenticator(
|
||||
case Method::CORP_SESSION_AUTHZ_SPAKE2_CURVE25519: {
|
||||
DCHECK(config_->session_authz_client_factory);
|
||||
auto authenticator = std::make_unique<SessionAuthzAuthenticator>(
|
||||
CredentialsType::CORP_SESSION_AUTHZ,
|
||||
config_->session_authz_client_factory->Create(),
|
||||
base::BindRepeating(&Spake2Authenticator::CreateForHost, local_id_,
|
||||
remote_id_, config_->local_cert,
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/logging.h"
|
||||
#include "remoting/base/constants.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
@ -23,6 +24,15 @@ const jingle_xmpp::StaticQName kPairingErrorAttribute = {"", "error"};
|
||||
PairingAuthenticatorBase::PairingAuthenticatorBase() {}
|
||||
PairingAuthenticatorBase::~PairingAuthenticatorBase() = default;
|
||||
|
||||
CredentialsType PairingAuthenticatorBase::credentials_type() const {
|
||||
return CredentialsType::PAIRED;
|
||||
}
|
||||
|
||||
const Authenticator& PairingAuthenticatorBase::implementing_authenticator()
|
||||
const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State PairingAuthenticatorBase::state() const {
|
||||
DCHECK(spake2_authenticator_);
|
||||
return spake2_authenticator_->state();
|
||||
|
@ -45,6 +45,8 @@ class PairingAuthenticatorBase : public Authenticator {
|
||||
~PairingAuthenticatorBase() override;
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -47,6 +47,9 @@ MockSession::~MockSession() = default;
|
||||
MockSessionManager::MockSessionManager() = default;
|
||||
MockSessionManager::~MockSessionManager() = default;
|
||||
|
||||
MockSessionObserver::MockSessionObserver() = default;
|
||||
MockSessionObserver::~MockSessionObserver() = default;
|
||||
|
||||
MockPairingRegistryDelegate::MockPairingRegistryDelegate() = default;
|
||||
MockPairingRegistryDelegate::~MockPairingRegistryDelegate() = default;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "remoting/protocol/pairing_registry.h"
|
||||
#include "remoting/protocol/session.h"
|
||||
#include "remoting/protocol/session_manager.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
#include "remoting/protocol/transport.h"
|
||||
#include "remoting/protocol/video_stub.h"
|
||||
#include "remoting/signaling/signaling_address.h"
|
||||
@ -45,6 +46,11 @@ class MockAuthenticator : public Authenticator {
|
||||
|
||||
~MockAuthenticator() override;
|
||||
|
||||
MOCK_METHOD(CredentialsType, credentials_type, (), (const, override));
|
||||
MOCK_METHOD(const Authenticator&,
|
||||
implementing_authenticator,
|
||||
(),
|
||||
(const, override));
|
||||
MOCK_CONST_METHOD0(state, Authenticator::State());
|
||||
MOCK_CONST_METHOD0(started, bool());
|
||||
MOCK_CONST_METHOD0(rejection_reason, Authenticator::RejectionReason());
|
||||
@ -217,10 +223,11 @@ class MockSession : public Session {
|
||||
~MockSession() override;
|
||||
|
||||
MOCK_METHOD1(SetEventHandler, void(Session::EventHandler* event_handler));
|
||||
MOCK_METHOD0(error, ErrorCode());
|
||||
MOCK_METHOD(ErrorCode, error, (), (const, override));
|
||||
MOCK_METHOD1(SetTransport, void(Transport*));
|
||||
MOCK_METHOD0(jid, const std::string&());
|
||||
MOCK_METHOD0(config, const SessionConfig&());
|
||||
MOCK_METHOD(const Authenticator&, authenticator, (), (const, override));
|
||||
MOCK_METHOD1(Close, void(ErrorCode error));
|
||||
MOCK_METHOD1(AddPlugin, void(SessionPlugin* plugin));
|
||||
};
|
||||
@ -243,6 +250,9 @@ class MockSessionManager : public SessionManager {
|
||||
MOCK_METHOD0(Close, void());
|
||||
MOCK_METHOD1(set_authenticator_factory_ptr,
|
||||
void(AuthenticatorFactory* factory));
|
||||
MOCK_METHOD(SessionObserver::Subscription,
|
||||
AddSessionObserver,
|
||||
(SessionObserver * observer));
|
||||
std::unique_ptr<Session> Connect(
|
||||
const SignalingAddress& peer_address,
|
||||
std::unique_ptr<Authenticator> authenticator) override {
|
||||
@ -254,6 +264,17 @@ class MockSessionManager : public SessionManager {
|
||||
}
|
||||
};
|
||||
|
||||
class MockSessionObserver : public SessionObserver {
|
||||
public:
|
||||
MockSessionObserver();
|
||||
~MockSessionObserver() override;
|
||||
|
||||
MockSessionObserver(const MockSessionObserver&) = delete;
|
||||
MockSessionObserver& operator=(const MockSessionObserver&) = delete;
|
||||
|
||||
MOCK_METHOD(void, OnSessionStateChange, (const Session&, Session::State));
|
||||
};
|
||||
|
||||
// Simple delegate that caches information on paired clients in memory.
|
||||
class MockPairingRegistryDelegate : public PairingRegistry::Delegate {
|
||||
public:
|
||||
|
@ -17,6 +17,15 @@ RejectingAuthenticator::RejectingAuthenticator(RejectionReason rejection_reason)
|
||||
|
||||
RejectingAuthenticator::~RejectingAuthenticator() = default;
|
||||
|
||||
CredentialsType RejectingAuthenticator::credentials_type() const {
|
||||
return CredentialsType::UNKNOWN;
|
||||
}
|
||||
|
||||
const Authenticator& RejectingAuthenticator::implementing_authenticator()
|
||||
const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State RejectingAuthenticator::state() const {
|
||||
return state_;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ class RejectingAuthenticator : public Authenticator {
|
||||
~RejectingAuthenticator() override;
|
||||
|
||||
// Authenticator interface
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
class Authenticator;
|
||||
class SessionPlugin;
|
||||
class Transport;
|
||||
|
||||
@ -71,7 +72,7 @@ class Session {
|
||||
virtual void SetEventHandler(EventHandler* event_handler) = 0;
|
||||
|
||||
// Returns error code for a failed session.
|
||||
virtual ErrorCode error() = 0;
|
||||
virtual ErrorCode error() const = 0;
|
||||
|
||||
// JID of the other side.
|
||||
virtual const std::string& jid() = 0;
|
||||
@ -80,6 +81,8 @@ class Session {
|
||||
// Returned pointer is valid until connection is closed.
|
||||
virtual const SessionConfig& config() = 0;
|
||||
|
||||
virtual const Authenticator& authenticator() const = 0;
|
||||
|
||||
// Sets Transport to be used by the session. Must be called before the
|
||||
// session becomes AUTHENTICATED. The transport must outlive the session.
|
||||
virtual void SetTransport(Transport* transport) = 0;
|
||||
|
@ -15,15 +15,21 @@
|
||||
#include "remoting/base/protobuf_http_status.h"
|
||||
#include "remoting/proto/session_authz_service.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/session_authz_reauthorizer.h"
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
SessionAuthzAuthenticator::SessionAuthzAuthenticator(
|
||||
CredentialsType credentials_type,
|
||||
std::unique_ptr<SessionAuthzServiceClient> service_client,
|
||||
const CreateBaseAuthenticatorCallback& create_base_authenticator_callback)
|
||||
: service_client_(std::move(service_client)),
|
||||
create_base_authenticator_callback_(create_base_authenticator_callback) {}
|
||||
: credentials_type_(credentials_type),
|
||||
service_client_(std::move(service_client)),
|
||||
create_base_authenticator_callback_(create_base_authenticator_callback) {
|
||||
// CORP_SESSION_AUTHZ is currently the only supported type.
|
||||
DCHECK_EQ(credentials_type, CredentialsType::CORP_SESSION_AUTHZ);
|
||||
}
|
||||
|
||||
SessionAuthzAuthenticator::~SessionAuthzAuthenticator() = default;
|
||||
|
||||
@ -31,6 +37,15 @@ void SessionAuthzAuthenticator::Start(base::OnceClosure resume_callback) {
|
||||
GenerateHostToken(std::move(resume_callback));
|
||||
}
|
||||
|
||||
CredentialsType SessionAuthzAuthenticator::credentials_type() const {
|
||||
return credentials_type_;
|
||||
}
|
||||
|
||||
const Authenticator& SessionAuthzAuthenticator::implementing_authenticator()
|
||||
const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State SessionAuthzAuthenticator::state() const {
|
||||
switch (session_authz_state_) {
|
||||
case SessionAuthzState::NOT_STARTED:
|
||||
@ -114,6 +129,11 @@ SessionAuthzAuthenticator::CreateChannelAuthenticator() const {
|
||||
return underlying_->CreateChannelAuthenticator();
|
||||
}
|
||||
|
||||
void SessionAuthzAuthenticator::SetReauthorizerForTesting(
|
||||
std::unique_ptr<SessionAuthzReauthorizer> reauthorizer) {
|
||||
reauthorizer_ = std::move(reauthorizer);
|
||||
}
|
||||
|
||||
void SessionAuthzAuthenticator::GenerateHostToken(
|
||||
base::OnceClosure resume_callback) {
|
||||
session_authz_state_ = SessionAuthzState::GENERATING_HOST_TOKEN;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "remoting/proto/session_authz_service.h"
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/channel_authenticator.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/session_authz_reauthorizer.h"
|
||||
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
|
||||
|
||||
@ -33,6 +34,7 @@ class SessionAuthzAuthenticator : public Authenticator {
|
||||
remoting::kChromotingXmlNamespace, "session-token"};
|
||||
|
||||
SessionAuthzAuthenticator(
|
||||
CredentialsType credentials_type,
|
||||
std::unique_ptr<SessionAuthzServiceClient> service_client,
|
||||
const CreateBaseAuthenticatorCallback&
|
||||
create_base_authenticator_callback);
|
||||
@ -46,7 +48,13 @@ class SessionAuthzAuthenticator : public Authenticator {
|
||||
// state until |resume_callback| is called.
|
||||
void Start(base::OnceClosure resume_callback);
|
||||
|
||||
const SessionAuthzReauthorizer* reauthorizer() const {
|
||||
return reauthorizer_.get();
|
||||
}
|
||||
|
||||
// Authenticator implementation.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
@ -57,6 +65,9 @@ class SessionAuthzAuthenticator : public Authenticator {
|
||||
std::unique_ptr<ChannelAuthenticator> CreateChannelAuthenticator()
|
||||
const override;
|
||||
|
||||
void SetReauthorizerForTesting(
|
||||
std::unique_ptr<SessionAuthzReauthorizer> reauthorizer);
|
||||
|
||||
private:
|
||||
enum class SessionAuthzState {
|
||||
NOT_STARTED,
|
||||
@ -106,6 +117,7 @@ class SessionAuthzAuthenticator : public Authenticator {
|
||||
void StartReauthorizerIfNecessary();
|
||||
void OnReauthorizationFailed();
|
||||
|
||||
CredentialsType credentials_type_;
|
||||
std::unique_ptr<SessionAuthzServiceClient> service_client_;
|
||||
CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
|
||||
std::unique_ptr<Authenticator> underlying_;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "remoting/protocol/authenticator.h"
|
||||
#include "remoting/protocol/authenticator_test_base.h"
|
||||
#include "remoting/protocol/connection_tester.h"
|
||||
#include "remoting/protocol/credentials_type.h"
|
||||
#include "remoting/protocol/spake2_authenticator.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
@ -74,6 +75,8 @@ class FakeClientAuthenticator : public Authenticator {
|
||||
~FakeClientAuthenticator() override;
|
||||
|
||||
// Authenticator implementation.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
@ -110,6 +113,15 @@ class FakeClientAuthenticator : public Authenticator {
|
||||
bool underlying_authenticator_message_suppressed_ = false;
|
||||
};
|
||||
|
||||
CredentialsType FakeClientAuthenticator::credentials_type() const {
|
||||
return CredentialsType::CORP_SESSION_AUTHZ;
|
||||
}
|
||||
|
||||
const Authenticator& FakeClientAuthenticator::implementing_authenticator()
|
||||
const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State FakeClientAuthenticator::state() const {
|
||||
switch (session_authz_state_) {
|
||||
case SessionAuthzState::READY_TO_SEND_SESSION_TOKEN:
|
||||
@ -225,7 +237,7 @@ void SessionAuthzAuthenticatorTest::SetUp() {
|
||||
auto mock_service_client = std::make_unique<MockSessionAuthzServiceClient>();
|
||||
mock_service_client_ = mock_service_client.get();
|
||||
auto host_authenticator = std::make_unique<SessionAuthzAuthenticator>(
|
||||
std::move(mock_service_client),
|
||||
CredentialsType::CORP_SESSION_AUTHZ, std::move(mock_service_client),
|
||||
base::BindRepeating(&Spake2Authenticator::CreateForHost, kHostId,
|
||||
kClientId, host_cert_, key_pair_));
|
||||
host_authenticator_ = host_authenticator.get();
|
||||
|
@ -43,6 +43,10 @@ class SessionAuthzReauthorizer {
|
||||
|
||||
const net::BackoffEntry* GetBackoffEntryForTest() const;
|
||||
|
||||
const std::string& session_reauth_token() const {
|
||||
return session_reauth_token_;
|
||||
}
|
||||
|
||||
private:
|
||||
void ScheduleNextReauth();
|
||||
void Reauthorize();
|
||||
|
@ -57,6 +57,7 @@
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "remoting/protocol/session.h"
|
||||
#include "remoting/protocol/session_observer.h"
|
||||
|
||||
namespace remoting {
|
||||
|
||||
@ -126,6 +127,11 @@ class SessionManager {
|
||||
// factory before all authenticators it created are deleted.
|
||||
virtual void set_authenticator_factory(
|
||||
std::unique_ptr<AuthenticatorFactory> authenticator_factory) = 0;
|
||||
|
||||
// Adds a session observer. Discarding the returned subscription will result
|
||||
// in the removal of the observer.
|
||||
[[nodiscard]] virtual SessionObserver::Subscription AddSessionObserver(
|
||||
SessionObserver* observer) = 0;
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
40
remoting/protocol/session_observer.h
Normal file
40
remoting/protocol/session_observer.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef REMOTING_PROTOCOL_SESSION_OBSERVER_H_
|
||||
#define REMOTING_PROTOCOL_SESSION_OBSERVER_H_
|
||||
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/observer_list_types.h"
|
||||
#include "remoting/protocol/session.h"
|
||||
|
||||
namespace remoting::protocol {
|
||||
|
||||
// An interface for observing session state changes. It is similar to
|
||||
// Session::EventHandler. The differences are:
|
||||
//
|
||||
// 1. The observer is registered on SessionManager, rather than the Session.
|
||||
// 2. Implementations will observe state changes from multiple sessions. The
|
||||
// |session| parameter will tell you which session's state has changed.
|
||||
// 3. Unlike Session::EventHandler, the SessionObserver is not supposed to
|
||||
// modify the Session. It is only supposed to observe the changes.
|
||||
//
|
||||
// An example of the observer is a logger that needs to know the error code and
|
||||
// the authentication type when the session state has changed.
|
||||
class SessionObserver : public base::CheckedObserver {
|
||||
public:
|
||||
using Subscription = base::ScopedClosureRunner;
|
||||
|
||||
// Called after session state has changed. The observer must not destroy the
|
||||
// session from within the method.
|
||||
virtual void OnSessionStateChange(const Session& session,
|
||||
Session::State state) = 0;
|
||||
|
||||
protected:
|
||||
SessionObserver() = default;
|
||||
};
|
||||
|
||||
} // namespace remoting::protocol
|
||||
|
||||
#endif // REMOTING_PROTOCOL_SESSION_OBSERVER_H_
|
@ -135,6 +135,14 @@ Spake2Authenticator::~Spake2Authenticator() {
|
||||
SPAKE2_CTX_free(spake2_context_);
|
||||
}
|
||||
|
||||
CredentialsType Spake2Authenticator::credentials_type() const {
|
||||
return CredentialsType::SHARED_SECRET;
|
||||
}
|
||||
|
||||
const Authenticator& Spake2Authenticator::implementing_authenticator() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Authenticator::State Spake2Authenticator::state() const {
|
||||
if (state_ == ACCEPTED && !outgoing_verification_hash_.empty()) {
|
||||
return MESSAGE_READY;
|
||||
|
@ -46,6 +46,8 @@ class Spake2Authenticator : public Authenticator {
|
||||
~Spake2Authenticator() override;
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -31,6 +31,15 @@ ThirdPartyAuthenticatorBase::ThirdPartyAuthenticatorBase(
|
||||
|
||||
ThirdPartyAuthenticatorBase::~ThirdPartyAuthenticatorBase() = default;
|
||||
|
||||
CredentialsType ThirdPartyAuthenticatorBase::credentials_type() const {
|
||||
return CredentialsType::THIRD_PARTY;
|
||||
}
|
||||
|
||||
const Authenticator& ThirdPartyAuthenticatorBase::implementing_authenticator()
|
||||
const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ThirdPartyAuthenticatorBase::started() const {
|
||||
return started_;
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ class ThirdPartyAuthenticatorBase : public Authenticator {
|
||||
~ThirdPartyAuthenticatorBase() override;
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
@ -34,6 +34,15 @@ ValidatingAuthenticator::ValidatingAuthenticator(
|
||||
|
||||
ValidatingAuthenticator::~ValidatingAuthenticator() = default;
|
||||
|
||||
CredentialsType ValidatingAuthenticator::credentials_type() const {
|
||||
return current_authenticator_->credentials_type();
|
||||
}
|
||||
|
||||
const Authenticator& ValidatingAuthenticator::implementing_authenticator()
|
||||
const {
|
||||
return current_authenticator_->implementing_authenticator();
|
||||
}
|
||||
|
||||
Authenticator::State ValidatingAuthenticator::state() const {
|
||||
return pending_auth_message_ ? MESSAGE_READY : state_;
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ class ValidatingAuthenticator : public Authenticator {
|
||||
~ValidatingAuthenticator() override;
|
||||
|
||||
// Authenticator interface.
|
||||
CredentialsType credentials_type() const override;
|
||||
const Authenticator& implementing_authenticator() const override;
|
||||
State state() const override;
|
||||
bool started() const override;
|
||||
RejectionReason rejection_reason() const override;
|
||||
|
Reference in New Issue
Block a user