#pragma once #include "ref.hpp" #include #include #include #include #include #include class SaslMechanism { public: struct NoReply {}; struct Failure {}; using StepResult = std::variant; virtual ~SaslMechanism() {} virtual auto mechanism_name() const -> std::string = 0; virtual auto step(std::string_view msg) -> StepResult = 0; virtual auto is_complete() const -> bool = 0; }; class SaslPlain final : public SaslMechanism { std::string authcid_; std::string authzid_; std::string password_; bool complete_; public: SaslPlain(std::string authcid, std::string authzid, std::string password) : authcid_{std::move(authcid)} , authzid_{std::move(authzid)} , password_{std::move(password)} , complete_{false} {} auto mechanism_name() const -> std::string override { return "PLAIN"; } auto step(std::string_view msg) -> StepResult override; auto is_complete() const -> bool override { return complete_; } }; class SaslExternal final : public SaslMechanism { std::string authzid_; bool complete_; public: SaslExternal(std::string authzid) : authzid_{std::move(authzid)} , complete_{false} {} auto mechanism_name() const -> std::string override { return "EXTERNAL"; } auto step(std::string_view msg) -> StepResult override; auto is_complete() const -> bool override { return complete_; } }; class SaslEcdsa final : public SaslMechanism { std::string message1_; Ref key_; int stage_; public: SaslEcdsa(std::string authcid, std::string authzid, Ref key) : message1_{std::move(authcid)} , key_{std::move(key)} , stage_{0} { if (not authzid.empty()) { message1_.push_back(0); message1_.append(authzid); } } auto mechanism_name() const -> std::string override { return "ECDSA-NIST256P-CHALLENGE"; } auto step(std::string_view msg) -> StepResult override; auto is_complete() const -> bool override { return stage_ == 2;; } };