1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// 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_AUTHZ_AUTHENTICATOR_H_
#define REMOTING_PROTOCOL_SESSION_AUTHZ_AUTHENTICATOR_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include "base/functional/callback.h"
#include "base/time/time.h"
#include "remoting/base/constants.h"
#include "remoting/base/http_status.h"
#include "remoting/base/session_authz_service_client.h"
#include "remoting/base/session_policies.h"
#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"
namespace remoting::protocol {
// Class that implements the host leg of the SessionAuthz mechanism. Note that
// this class only handles the initial authorization process. Inter-session
// reauthorization will be handled by a different class.
// See go/crd-sessionauthz-integration for internal details.
class SessionAuthzAuthenticator : public Authenticator {
public:
static constexpr jingle_xmpp::StaticQName kHostTokenTag = {
remoting::kChromotingXmlNamespace, "host-token"};
static constexpr jingle_xmpp::StaticQName kSessionTokenTag = {
remoting::kChromotingXmlNamespace, "session-token"};
SessionAuthzAuthenticator(
CredentialsType credentials_type,
std::unique_ptr<SessionAuthzServiceClient> service_client,
const CreateBaseAuthenticatorCallback&
create_base_authenticator_callback);
~SessionAuthzAuthenticator() override;
SessionAuthzAuthenticator(const SessionAuthzAuthenticator&) = delete;
SessionAuthzAuthenticator& operator=(const SessionAuthzAuthenticator&) =
delete;
// Start the authenticator. The authenticator won't be in the `MESSAGE_READY`
// state until |resume_callback| is called.
void Start(base::OnceClosure resume_callback);
const SessionAuthzReauthorizer* reauthorizer() const {
return reauthorizer_.get();
}
// The session ID generated by the SessionAuthz server. This is only set if
// the GenerateHostToken API call has completed and succeeded. Otherwise, this
// will be an empty string.
const std::string& session_id() const { return session_id_; }
// The host token returned by the SessionAuthz server. This is only set if
// the GenerateHostToken API call has completed and succeeded. Otherwise, this
// will be an empty string.
const std::string& host_token() const { return host_token_; }
// 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;
RejectionDetails rejection_details() const override;
void ProcessMessage(const jingle_xmpp::XmlElement* message,
base::OnceClosure resume_callback) override;
std::unique_ptr<jingle_xmpp::XmlElement> GetNextMessage() override;
const std::string& GetAuthKey() const override;
const SessionPolicies* GetSessionPolicies() const override;
std::unique_ptr<ChannelAuthenticator> CreateChannelAuthenticator()
const override;
void SetReauthorizerForTesting(
std::unique_ptr<SessionAuthzReauthorizer> reauthorizer);
void SetSessionIdForTesting(std::string_view session_id);
void SetHostTokenForTesting(std::string_view host_token);
private:
enum class SessionAuthzState {
NOT_STARTED,
// A request was made to call GenerateHostToken on SessionAuthz, and the
// response is pending.
GENERATING_HOST_TOKEN,
// The response for GenerateHostToken has been received, and is ready to be
// sent to the client.
READY_TO_SEND_HOST_TOKEN,
// Waiting for the client to send the session token.
WAITING_FOR_SESSION_TOKEN,
// A request was made to call VerifySessionToken on SessionAuthz, with the
// session token sent by the client, and the response is pending.
VERIFYING_SESSION_TOKEN,
// The shared secret has been returned by the VerifySessionToken call. The
// rest of the authentication process is now handed over to the underlying
// authenticator.
SHARED_SECRET_FETCHED,
// An error has occurred when trying to fetch the shared secret. Note that
// an error might occur in the underlying authenticator, in which case the
// SessionAuthz state will be `SHARED_SECRET_FETCHED` and
// `underlying_->state()` will be `REJECTED`.
FAILED,
};
void GenerateHostToken(base::OnceClosure resume_callback);
void OnHostTokenGenerated(
base::OnceClosure resume_callback,
const HttpStatus& status,
std::unique_ptr<internal::GenerateHostTokenResponseStruct> response);
void AddHostTokenElement(jingle_xmpp::XmlElement* message);
void VerifySessionToken(const jingle_xmpp::XmlElement& message,
base::OnceClosure resume_callback);
void OnVerifiedSessionToken(
const jingle_xmpp::XmlElement& message,
base::OnceClosure resume_callback,
const HttpStatus& status,
std::unique_ptr<internal::VerifySessionTokenResponseStruct> response);
void HandleSessionAuthzError(const std::string_view& action_name,
const HttpStatus& status);
void StartReauthorizerIfNecessary();
void OnReauthorizationFailed(HttpStatus::Code error_code,
const Authenticator::RejectionDetails& details);
CredentialsType credentials_type_;
std::unique_ptr<SessionAuthzServiceClient> service_client_;
CreateBaseAuthenticatorCallback create_base_authenticator_callback_;
std::unique_ptr<Authenticator> underlying_;
std::unique_ptr<internal::VerifySessionTokenResponseStruct>
verify_token_response_;
std::optional<SessionPolicies> session_policies_;
std::unique_ptr<SessionAuthzReauthorizer> reauthorizer_;
SessionAuthzState session_authz_state_ = SessionAuthzState::NOT_STARTED;
// The rejection reason specific to fetching the shared secret from
// SessionAuthz. If |session_authz_state_| is NOT `ERROR`, the actual
// rejection reason is delegated to `underlying_->rejection_reason()`.
RejectionReason session_authz_rejection_reason_;
RejectionDetails rejection_details_;
std::string session_id_;
std::string host_token_;
};
} // namespace remoting::protocol
#endif // REMOTING_PROTOCOL_SESSION_AUTHZ_AUTHENTICATOR_H_
|