challenge.cpp
This commit is contained in:
parent
21090f05ab
commit
de19233dd7
90
challenge.cpp
Normal file
90
challenge.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "challenge.hpp"
|
||||||
|
|
||||||
|
#include "openssl_errors.hpp"
|
||||||
|
|
||||||
|
#include <mybase64.hpp>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
Challenge::Challenge(EVP_PKEY_Ref key, Connection & connection)
|
||||||
|
: key_{std::move(key)}
|
||||||
|
, connection_{connection}
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
auto Challenge::stop() -> void
|
||||||
|
{
|
||||||
|
slot_.disconnect();
|
||||||
|
buffer_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Challenge::on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void {
|
||||||
|
switch (cmd) {
|
||||||
|
default: break;
|
||||||
|
case IrcCommand::RPL_RSACHALLENGE2:
|
||||||
|
buffer_ += msg.args[1];
|
||||||
|
break;
|
||||||
|
case IrcCommand::ERR_NOOPERHOST:
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Challenge: No oper host";
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
case IrcCommand::RPL_YOUREOPER:
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Challenge: Already oper";
|
||||||
|
stop();
|
||||||
|
break;
|
||||||
|
case IrcCommand::RPL_ENDOFRSACHALLENGE2:
|
||||||
|
{
|
||||||
|
EVP_PKEY_CTX_Ref ctx;
|
||||||
|
unsigned int digestlen = 160;
|
||||||
|
unsigned char digest[160];
|
||||||
|
size_t len = mybase64::decoded_size(buffer_.size());
|
||||||
|
std::vector<unsigned char> ciphertext(len, 0);
|
||||||
|
|
||||||
|
if (not mybase64::decode(buffer_, reinterpret_cast<char*>(ciphertext.data()), &len)) goto error;
|
||||||
|
ciphertext.resize(len);
|
||||||
|
|
||||||
|
// Setup decryption context
|
||||||
|
ctx.reset(EVP_PKEY_CTX_new(key_.get(), nullptr));
|
||||||
|
if (ctx.get() == nullptr) 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;
|
||||||
|
|
||||||
|
// Determine output size
|
||||||
|
if (1 != EVP_PKEY_decrypt(ctx.get(), nullptr, &len, ciphertext.data(), ciphertext.size())) goto error;
|
||||||
|
buffer_.resize(len);
|
||||||
|
|
||||||
|
// Decrypt ciphertext
|
||||||
|
EVP_PKEY_decrypt(ctx.get(), reinterpret_cast<unsigned char*>(buffer_.data()), &len, ciphertext.data(), ciphertext.size());
|
||||||
|
|
||||||
|
// Hash the decrypted message
|
||||||
|
if (1 != EVP_Digest(buffer_.data(), buffer_.size(), digest, &digestlen, EVP_sha1(), nullptr)) goto error;
|
||||||
|
|
||||||
|
// Construct reply as '+' and base64 encoded digest
|
||||||
|
buffer_.resize(mybase64::encoded_size(digestlen) + 1);
|
||||||
|
buffer_[0] = '+';
|
||||||
|
mybase64::encode(std::string_view{(char*)digest, digestlen}, buffer_.data() + 1);
|
||||||
|
|
||||||
|
connection_.send_challenge(buffer_);
|
||||||
|
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
log_openssl_errors("Challenge: ");
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Challenge::start(Connection &connection, const std::string_view user, EVP_PKEY_Ref ref) -> std::shared_ptr<Challenge>
|
||||||
|
{
|
||||||
|
auto self = std::make_shared<Challenge>(std::move(ref), connection);
|
||||||
|
connection.sig_ircmsg.connect([self](auto cmd, auto &msg) { self->on_ircmsg(cmd, msg); });
|
||||||
|
connection.send_challenge(user);
|
||||||
|
return self;
|
||||||
|
}
|
24
challenge.hpp
Normal file
24
challenge.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "connection.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
|
|
||||||
|
#include <boost/signals2/connection.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Challenge : std::enable_shared_from_this<Challenge>
|
||||||
|
{
|
||||||
|
EVP_PKEY_Ref key_;
|
||||||
|
Connection &connection_;
|
||||||
|
boost::signals2::scoped_connection slot_;
|
||||||
|
std::string buffer_;
|
||||||
|
|
||||||
|
auto on_ircmsg(IrcCommand cmd, const IrcMsg &msg) -> void;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Challenge(EVP_PKEY_Ref, Connection &);
|
||||||
|
auto stop() -> void;
|
||||||
|
static auto start(Connection &, std::string_view user, EVP_PKEY_Ref) -> std::shared_ptr<Challenge>;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user