fixup challenge
This commit is contained in:
parent
72b2756f34
commit
1aa56453cc
@ -46,7 +46,6 @@ add_executable(xbot
|
|||||||
challenge.cpp
|
challenge.cpp
|
||||||
client.cpp
|
client.cpp
|
||||||
connection.cpp
|
connection.cpp
|
||||||
irc_coroutine.cpp
|
|
||||||
ircmsg.cpp
|
ircmsg.cpp
|
||||||
openssl_errors.cpp
|
openssl_errors.cpp
|
||||||
registration.cpp
|
registration.cpp
|
||||||
|
@ -39,9 +39,11 @@ auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
|||||||
break;
|
break;
|
||||||
case IrcCommand::RPL_ENDOFRSACHALLENGE2:
|
case IrcCommand::RPL_ENDOFRSACHALLENGE2:
|
||||||
{
|
{
|
||||||
|
slot_.disconnect();
|
||||||
|
|
||||||
EVP_PKEY_CTX_Ref ctx;
|
EVP_PKEY_CTX_Ref ctx;
|
||||||
unsigned int digestlen = 160;
|
unsigned int digestlen = EVP_MAX_MD_SIZE;
|
||||||
unsigned char digest[160];
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
size_t len = mybase64::decoded_size(buffer_.size());
|
size_t len = mybase64::decoded_size(buffer_.size());
|
||||||
std::vector<unsigned char> ciphertext(len, 0);
|
std::vector<unsigned char> ciphertext(len, 0);
|
||||||
|
|
||||||
@ -52,14 +54,15 @@ auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
|||||||
ctx.reset(EVP_PKEY_CTX_new(key_.get(), nullptr));
|
ctx.reset(EVP_PKEY_CTX_new(key_.get(), nullptr));
|
||||||
if (ctx.get() == nullptr) goto error;
|
if (ctx.get() == nullptr) goto error;
|
||||||
if (1 != EVP_PKEY_decrypt_init(ctx.get())) goto error;
|
if (1 != EVP_PKEY_decrypt_init(ctx.get())) goto error;
|
||||||
if (0 <= EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING)) goto error;
|
if (0 >= EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING)) goto error;
|
||||||
|
|
||||||
// Determine output size
|
// Determine output size
|
||||||
if (1 != EVP_PKEY_decrypt(ctx.get(), nullptr, &len, ciphertext.data(), ciphertext.size())) goto error;
|
if (1 != EVP_PKEY_decrypt(ctx.get(), nullptr, &len, ciphertext.data(), ciphertext.size())) goto error;
|
||||||
buffer_.resize(len);
|
buffer_.resize(len);
|
||||||
|
|
||||||
// Decrypt ciphertext
|
// Decrypt ciphertext
|
||||||
EVP_PKEY_decrypt(ctx.get(), reinterpret_cast<unsigned char*>(buffer_.data()), &len, ciphertext.data(), ciphertext.size());
|
if (1 != EVP_PKEY_decrypt(ctx.get(), reinterpret_cast<unsigned char*>(buffer_.data()), &len, ciphertext.data(), ciphertext.size())) goto error;
|
||||||
|
buffer_.resize(len);
|
||||||
|
|
||||||
// Hash the decrypted message
|
// Hash the decrypted message
|
||||||
if (1 != EVP_Digest(buffer_.data(), buffer_.size(), digest, &digestlen, EVP_sha1(), nullptr)) goto error;
|
if (1 != EVP_Digest(buffer_.data(), buffer_.size(), digest, &digestlen, EVP_sha1(), nullptr)) goto error;
|
||||||
@ -70,13 +73,10 @@ auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
|||||||
mybase64::encode(std::string_view{(char*)digest, digestlen}, buffer_.data() + 1);
|
mybase64::encode(std::string_view{(char*)digest, digestlen}, buffer_.data() + 1);
|
||||||
|
|
||||||
connection_.send_challenge(buffer_);
|
connection_.send_challenge(buffer_);
|
||||||
|
|
||||||
stop();
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
log_openssl_errors("Challenge: ");
|
log_openssl_errors("Challenge: ");
|
||||||
stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
#include "irc_coroutine.hpp"
|
|
||||||
|
|
||||||
auto irc_coroutine::is_running() -> bool
|
|
||||||
{
|
|
||||||
return promise().connection_ != nullptr;
|
|
||||||
}
|
|
||||||
auto irc_coroutine::exception() -> std::exception_ptr
|
|
||||||
{
|
|
||||||
return promise().exception_;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto irc_coroutine::start(Connection &connection) -> void
|
|
||||||
{
|
|
||||||
promise().connection_ = connection.shared_from_this();
|
|
||||||
resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
void wait_ircmsg::stop() { ircmsg_slot_.disconnect(); }
|
|
||||||
|
|
||||||
void wait_timeout::stop() { timer_.reset(); }
|
|
@ -80,7 +80,28 @@ public:
|
|||||||
|
|
||||||
template <size_t I, typename... Ts>
|
template <size_t I, typename... Ts>
|
||||||
auto start(Wait<Ts...> &command) -> void;
|
auto start(Wait<Ts...> &command) -> void;
|
||||||
auto stop() -> void;
|
auto stop() -> void { ircmsg_slot_.disconnect(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class wait_snote
|
||||||
|
{
|
||||||
|
// Vector of tags this wait is expecting. Leave empty to accept all messages.
|
||||||
|
std::vector<SnoteTag> want_tags_;
|
||||||
|
|
||||||
|
// Slot for the snote event
|
||||||
|
boost::signals2::scoped_connection snote_slot_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using result_type = SnoteMatch;
|
||||||
|
|
||||||
|
wait_snote(std::initializer_list<SnoteTag> want_tags)
|
||||||
|
: want_tags_{want_tags}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t I, typename... Ts>
|
||||||
|
auto start(Wait<Ts...> &command) -> void;
|
||||||
|
auto stop() -> void { snote_slot_.disconnect(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class wait_timeout
|
class wait_timeout
|
||||||
@ -99,7 +120,7 @@ public:
|
|||||||
|
|
||||||
template <size_t I, typename... Ts>
|
template <size_t I, typename... Ts>
|
||||||
auto start(Wait<Ts...> &command) -> void;
|
auto start(Wait<Ts...> &command) -> void;
|
||||||
auto stop() -> void;
|
auto stop() -> void { timer_->cancel(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
@ -180,6 +201,19 @@ auto wait_ircmsg::start(Wait<Ts...> &command) -> void
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <size_t I, typename... Ts>
|
||||||
|
auto wait_snote::start(Wait<Ts...> &command) -> void
|
||||||
|
{
|
||||||
|
snote_slot_ = command.get_connection().sig_snote.connect([this, &command](auto &match) {
|
||||||
|
const auto tag = match.get_tag();
|
||||||
|
const auto wanted = want_tags_.empty() || std::find(want_tags_.begin(), want_tags_.end(), tag) != want_tags_.end();
|
||||||
|
if (wanted)
|
||||||
|
{
|
||||||
|
command.template complete<I>(match);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template <size_t I, typename... Ts>
|
template <size_t I, typename... Ts>
|
||||||
auto wait_timeout::start(Wait<Ts...> &command) -> void
|
auto wait_timeout::start(Wait<Ts...> &command) -> void
|
||||||
{
|
{
|
||||||
@ -224,3 +258,21 @@ auto Wait<Ts...>::await_resume() -> std::variant<typename Ts::result_type...>
|
|||||||
throw std::runtime_error{"connection terminated"};
|
throw std::runtime_error{"connection terminated"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start the coroutine and associate it with a specific connection.
|
||||||
|
inline auto irc_coroutine::start(Connection &connection) -> void
|
||||||
|
{
|
||||||
|
promise().connection_ = connection.shared_from_this();
|
||||||
|
resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true when this coroutine is still waiting on events
|
||||||
|
inline auto irc_coroutine::is_running() -> bool
|
||||||
|
{
|
||||||
|
return promise().connection_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto irc_coroutine::exception() -> std::exception_ptr
|
||||||
|
{
|
||||||
|
return promise().exception_;
|
||||||
|
}
|
||||||
|
15
main.cpp
15
main.cpp
@ -6,6 +6,7 @@
|
|||||||
#include "openssl_errors.hpp"
|
#include "openssl_errors.hpp"
|
||||||
#include "registration.hpp"
|
#include "registration.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "irc_coroutine.hpp"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
@ -130,22 +131,26 @@ static auto start(boost::asio::io_context &io, const Settings &settings) -> void
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto get_settings() -> Settings
|
static auto get_settings(const char *filename) -> Settings
|
||||||
{
|
{
|
||||||
if (auto config_stream = std::ifstream{"config.toml"})
|
if (auto config_stream = std::ifstream{filename})
|
||||||
{
|
{
|
||||||
return Settings::from_stream(config_stream);
|
return Settings::from_stream(config_stream);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(error) << "Unable to open config.toml";
|
BOOST_LOG_TRIVIAL(error) << "Unable to open configuration";
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto main() -> int
|
auto main(int argc, char *argv[]) -> int
|
||||||
{
|
{
|
||||||
const auto settings = get_settings();
|
if (argc != 2) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Bad arguments";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const auto settings = get_settings(argv[1]);
|
||||||
auto io = boost::asio::io_context{};
|
auto io = boost::asio::io_context{};
|
||||||
start(io, settings);
|
start(io, settings);
|
||||||
io.run();
|
io.run();
|
||||||
|
@ -81,12 +81,14 @@ auto Registration::on_cap_list(const std::unordered_map<std::string, std::string
|
|||||||
client_->get_connection().send_cap_req(request);
|
client_->get_connection().send_cap_req(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_sasl) {
|
if (do_sasl && settings_.sasl_mechanism == "PLAIN") {
|
||||||
client_->start_sasl(
|
client_->start_sasl(
|
||||||
std::make_unique<SaslPlain>(
|
std::make_unique<SaslPlain>(
|
||||||
settings_.sasl_authcid,
|
settings_.sasl_authcid,
|
||||||
settings_.sasl_authzid,
|
settings_.sasl_authzid,
|
||||||
settings_.sasl_password));
|
settings_.sasl_password));
|
||||||
|
} else if (do_sasl && settings_.sasl_mechanism == "EXTERNAL") {
|
||||||
|
client_->start_sasl(std::make_unique<SaslExternal>(settings_.sasl_authzid));
|
||||||
} else {
|
} else {
|
||||||
client_->get_connection().send_cap_end();
|
client_->get_connection().send_cap_end();
|
||||||
}
|
}
|
||||||
|
@ -17,3 +17,11 @@ auto SaslPlain::step(std::string_view msg) -> std::optional<std::string> {
|
|||||||
return {std::move(reply)};
|
return {std::move(reply)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto SaslExternal::step(std::string_view msg) -> std::optional<std::string> {
|
||||||
|
if (complete_) {
|
||||||
|
return std::nullopt;
|
||||||
|
} else {
|
||||||
|
return {std::move(authzid_)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -44,3 +44,27 @@ public:
|
|||||||
return complete_;
|
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) -> std::optional<std::string> override;
|
||||||
|
|
||||||
|
auto is_complete() const -> bool override
|
||||||
|
{
|
||||||
|
return complete_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -74,6 +74,12 @@ const SnotePattern static patterns[] = {
|
|||||||
|
|
||||||
{SnoteTag::SetVhostOnMarkedAccount,
|
{SnoteTag::SetVhostOnMarkedAccount,
|
||||||
"^\x02([^ ]+)\x02 set vhost ([^ ]+) on the \x02MARKED\x02 account ([^ ]+).$"},
|
"^\x02([^ ]+)\x02 set vhost ([^ ]+) on the \x02MARKED\x02 account ([^ ]+).$"},
|
||||||
|
|
||||||
|
{SnoteTag::IsNowOper,
|
||||||
|
R"(^([^ ]+) \(([^ ]+)!([^ ]+)@([^ ]+)\) is now an operator$)"},
|
||||||
|
|
||||||
|
{SnoteTag::NickCollision,
|
||||||
|
R"(^Nick collision due to services forced nick change on ([^ ]+)$)"},
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto setup_database() -> hs_database_t *
|
static auto setup_database() -> hs_database_t *
|
||||||
|
Loading…
x
Reference in New Issue
Block a user