2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-22 09:57:41 +00:00

[#3553] Checkpoint

This commit is contained in:
Francis Dupont 2024-08-31 12:15:38 +02:00
parent 9566324f68
commit a140a853c9
6 changed files with 236 additions and 39 deletions

View File

@ -1658,7 +1658,12 @@ TEST_F(HAConfigTest, badTrustAnchor) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
expected += "No such file or directory"; expected += "No such file or directory";
#else #else
expected += "I/O error: DataSource: Failure opening file /this-file-does-not-exist"; expected += "I/O error: DataSource: Failure opening file ";
#if BOTAN_VERSION_MAJOR > 2
expected += "'/this-file-does-not-exist'";
#else
expected += "/this-file-does-not-exist";
#endif
#endif #endif
testInvalidConfig(patched, expected); testInvalidConfig(patched, expected);
} }
@ -1698,7 +1703,12 @@ TEST_F(HAConfigTest, badCertFile) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
expected += "No such file or directory"; expected += "No such file or directory";
#else #else
expected += "I/O error: DataSource: Failure opening file /this-file-does-not-exist"; expected += "I/O error: DataSource: Failure opening file ";
#if BOTAN_VERSION_MAJOR > 2
expected += "'/this-file-does-not-exist'";
#else
expected += "/this-file-does-not-exist";
#endif
#endif #endif
testInvalidConfig(patched, expected); testInvalidConfig(patched, expected);
} }
@ -1738,7 +1748,12 @@ TEST_F(HAConfigTest, badKeyFile) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
expected += "No such file or directory"; expected += "No such file or directory";
#else #else
expected += "I/O error: DataSource: Failure opening file /this-file-does-not-exist"; expected += "I/O error: DataSource: Failure opening file ";
#if BOTAN_VERSION_MAJOR > 2
expected += "'/this-file-does-not-exist'";
#else
expected += "/this-file-does-not-exist";
#endif
#endif #endif
testInvalidConfig(patched, expected); testInvalidConfig(patched, expected);
} }

View File

@ -18,6 +18,9 @@
#include <botan/data_src.h> #include <botan/data_src.h>
#include <botan/pem.h> #include <botan/pem.h>
#include <botan/pkcs8.h> #include <botan/pkcs8.h>
#if BOTAN_VERSION_MAJOR > 2
#include <botan/tls_session_manager_noop.h>
#endif
using namespace isc::cryptolink; using namespace isc::cryptolink;
@ -36,8 +39,7 @@ public:
} }
// Destructor. // Destructor.
virtual ~KeaCredentialsManager() { virtual ~KeaCredentialsManager() = default;
}
// CA certificate stores. // CA certificate stores.
// nullptr means do not require or check peer certificate. // nullptr means do not require or check peer certificate.
@ -54,17 +56,28 @@ public:
// Certificate chain. // Certificate chain.
std::vector<Botan::X509_Certificate> std::vector<Botan::X509_Certificate>
cert_chain(const std::vector<std::string>&, cert_chain(const std::vector<std::string>&,
#if BOTAN_VERSION_MAJOR > 2
const std::vector<Botan::AlgorithmIdentifier>&,
#endif
const std::string&, const std::string&,
const std::string&) override { const std::string&) override {
return (certs_); return (certs_);
} }
// Private key. // Private key.
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::Private_Key>
#else
Botan::Private_Key* Botan::Private_Key*
#endif
private_key_for(const Botan::X509_Certificate&, private_key_for(const Botan::X509_Certificate&,
const std::string&, const std::string&,
const std::string&) override { const std::string&) override {
#if BOTAN_VERSION_MAJOR > 2
return (key_);
#else
return (key_.get()); return (key_.get());
#endif
} }
// Set the store from a path. // Set the store from a path.
@ -118,13 +131,27 @@ public:
// Set the private key. // Set the private key.
void setPrivateKey(const std::string& file, void setPrivateKey(const std::string& file,
#if BOTAN_VERSION_MAJOR > 2
Botan::RandomNumberGenerator&,
#else
Botan::RandomNumberGenerator& rng, Botan::RandomNumberGenerator& rng,
#endif
bool& is_rsa) { bool& is_rsa) {
key_.reset(Botan::PKCS8::load_key(file, rng)); #if BOTAN_VERSION_MAJOR > 2
if (!key_) { Botan::DataSource_Stream source(file);
auto priv_key = Botan::PKCS8::load_key(source);
#else
auto priv_key = Botan::PKCS8::load_key(file, rng);
#endif
if (!priv_key) {
isc_throw(Unexpected, isc_throw(Unexpected,
"Botan::PKCS8::load_key failed but not threw?"); "Botan::PKCS8::load_key failed but not threw?");
} }
#if BOTAN_VERSION_MAJOR > 2
key_ = std::move(priv_key);
#else
key_.reset(priv_key);
#endif
is_rsa = (key_->algo_name() == "RSA"); is_rsa = (key_->algo_name() == "RSA");
} }
@ -138,7 +165,7 @@ public:
std::vector<Botan::X509_Certificate> certs_; std::vector<Botan::X509_Certificate> certs_;
// Pointer to the private key. // Pointer to the private key.
std::unique_ptr<Botan::Private_Key> key_; std::shared_ptr<Botan::Private_Key> key_;
}; };
// Class of Kea policy. // Class of Kea policy.
@ -197,29 +224,32 @@ KeaPolicy::AllowedSignatureMethodsECDSA = { "ECDSA", "RSA", "DSA" };
class TlsContextImpl { class TlsContextImpl {
public: public:
// Constructor. // Constructor.
TlsContextImpl() : cred_mgr_(), rng_(), sess_mgr_(), policy_() { TlsContextImpl() :
cred_mgr_(new KeaCredentialsManager()),
rng_(new Botan::AutoSeeded_RNG()),
sess_mgr_(new KeaSessionManager()),
policy_(new KeaPolicy()) {
} }
// Destructor. // Destructor.
virtual ~TlsContextImpl() { virtual ~TlsContextImpl() = default;
}
// Get the peer certificate requirement mode. // Get the peer certificate requirement mode.
virtual bool getCertRequired() const { virtual bool getCertRequired() const {
return (cred_mgr_.getUseStores()); return (cred_mgr_->getUseStores());
} }
// Set the peer certificate requirement mode. // Set the peer certificate requirement mode.
// //
// With Botan this means to provide or not the CA certificate stores. // With Botan this means to provide or not the CA certificate stores.
virtual void setCertRequired(bool cert_required) { virtual void setCertRequired(bool cert_required) {
cred_mgr_.setUseStores(cert_required); cred_mgr_->setUseStores(cert_required);
} }
// Load the trust anchor aka certificate authority (path). // Load the trust anchor aka certificate authority (path).
virtual void loadCaPath(const std::string& ca_path) { virtual void loadCaPath(const std::string& ca_path) {
try { try {
cred_mgr_.setStorePath(ca_path); cred_mgr_->setStorePath(ca_path);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(LibraryError, ex.what()); isc_throw(LibraryError, ex.what());
} }
@ -228,7 +258,7 @@ public:
// Load the trust anchor aka certificate authority (file). // Load the trust anchor aka certificate authority (file).
virtual void loadCaFile(const std::string& ca_file) { virtual void loadCaFile(const std::string& ca_file) {
try { try {
cred_mgr_.setStoreFile(ca_file); cred_mgr_->setStoreFile(ca_file);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(LibraryError, ex.what()); isc_throw(LibraryError, ex.what());
} }
@ -237,7 +267,7 @@ public:
/// @brief Load the certificate file. /// @brief Load the certificate file.
virtual void loadCertFile(const std::string& cert_file) { virtual void loadCertFile(const std::string& cert_file) {
try { try {
cred_mgr_.setCertChain(cert_file); cred_mgr_->setCertChain(cert_file);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(LibraryError, ex.what()); isc_throw(LibraryError, ex.what());
} }
@ -249,8 +279,8 @@ public:
virtual void loadKeyFile(const std::string& key_file) { virtual void loadKeyFile(const std::string& key_file) {
try { try {
bool is_rsa = true; bool is_rsa = true;
cred_mgr_.setPrivateKey(key_file, rng_, is_rsa); cred_mgr_->setPrivateKey(key_file, *rng_, is_rsa);
policy_.setPrefRSA(is_rsa); policy_->setPrefRSA(is_rsa);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(LibraryError, ex.what()); isc_throw(LibraryError, ex.what());
} }
@ -261,28 +291,41 @@ public:
if (context_) { if (context_) {
return; return;
} }
#if BOTAN_VERSION_MAJOR > 2
context_.reset(new Botan::TLS::Context(cred_mgr_, context_.reset(new Botan::TLS::Context(cred_mgr_,
rng_, rng_,
sess_mgr_, sess_mgr_,
policy_)); policy_));
#else
context_.reset(new Botan::TLS::Context(*cred_mgr_,
*rng_,
*sess_mgr_,
*policy_));
#endif
} }
#if BOTAN_VERSION_MAJOR > 2
virtual std::shared_ptr<Botan::TLS::Context> get() {
return (context_);
}
#else
virtual Botan::TLS::Context& get() { virtual Botan::TLS::Context& get() {
return (*context_); return (*context_);
} }
#endif
// Credentials Manager. // Credentials Manager.
KeaCredentialsManager cred_mgr_; std::shared_ptr<KeaCredentialsManager> cred_mgr_;
// Random Number Generator. // Random Number Generator.
Botan::AutoSeeded_RNG rng_; std::shared_ptr<Botan::AutoSeeded_RNG> rng_;
// Session Manager. // Session Manager.
KeaSessionManager sess_mgr_; std::shared_ptr<KeaSessionManager> sess_mgr_;
KeaPolicy policy_; std::shared_ptr<KeaPolicy> policy_;
std::unique_ptr<Botan::TLS::Context> context_; std::shared_ptr<Botan::TLS::Context> context_;
}; };
TlsContext::~TlsContext() { TlsContext::~TlsContext() {
@ -292,11 +335,19 @@ TlsContext::TlsContext(TlsRole role)
: TlsContextBase(role), impl_(new TlsContextImpl()) { : TlsContextBase(role), impl_(new TlsContextImpl()) {
} }
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::TLS::Context>
TlsContext::getContext() {
impl_->build();
return (impl_->get());
}
#else
Botan::TLS::Context& Botan::TLS::Context&
TlsContext::getContext() { TlsContext::getContext() {
impl_->build(); impl_->build();
return (impl_->get()); return (impl_->get());
} }
#endif
void void
TlsContext::setCertRequired(bool cert_required) { TlsContext::setCertRequired(bool cert_required) {

View File

@ -28,9 +28,17 @@ namespace asiolink {
/// @brief Translate TLS role into implementation. /// @brief Translate TLS role into implementation.
inline Botan::TLS::Connection_Side roleToImpl(TlsRole role) { inline Botan::TLS::Connection_Side roleToImpl(TlsRole role) {
if (role == TlsRole::SERVER) { if (role == TlsRole::SERVER) {
#if BOTAN_VERSION_MAJOR > 2
return (Botan::TLS::Connection_Side::Server);
#else
return (Botan::TLS::Connection_Side::SERVER); return (Botan::TLS::Connection_Side::SERVER);
#endif
} else { } else {
#if BOTAN_VERSION_MAJOR > 2
return (Botan::TLS::Connection_Side::Client);
#else
return (Botan::TLS::Connection_Side::CLIENT); return (Botan::TLS::Connection_Side::CLIENT);
#endif
} }
} }
@ -53,7 +61,11 @@ public:
explicit TlsContext(TlsRole role); explicit TlsContext(TlsRole role);
/// @brief Return the underlying context. /// @brief Return the underlying context.
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::TLS::Context> getContext();
#else
Botan::TLS::Context& getContext(); Botan::TLS::Context& getContext();
#endif
/// @brief Get the peer certificate requirement mode. /// @brief Get the peer certificate requirement mode.
/// ///

View File

@ -509,6 +509,7 @@ TEST_F(TLSTest, loadNoCAFile) {
Expecteds exps; Expecteds exps;
// Botan error. // Botan error.
exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file"); exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file");
exps.addThrow("I/O error: DataSource: Failure opening file '/no-such-file'");
// OpenSSL errors. // OpenSSL errors.
exps.addThrow("No such file or directory"); exps.addThrow("No such file or directory");
exps.addThrow("No such file or directory (system library)"); exps.addThrow("No such file or directory (system library)");
@ -586,6 +587,7 @@ TEST_F(TLSTest, loadNoCertFile) {
Expecteds exps; Expecteds exps;
// Botan error. // Botan error.
exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file"); exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file");
exps.addThrow("I/O error: DataSource: Failure opening file '/no-such-file'");
// OpenSSL errors. // OpenSSL errors.
exps.addThrow("No such file or directory"); exps.addThrow("No such file or directory");
exps.addThrow("No such file or directory (system library)"); exps.addThrow("No such file or directory (system library)");
@ -632,6 +634,7 @@ TEST_F(TLSTest, loadNoKeyFile) {
Expecteds exps; Expecteds exps;
// Botan error. // Botan error.
exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file"); exps.addThrow("I/O error: DataSource: Failure opening file /no-such-file");
exps.addThrow("I/O error: DataSource: Failure opening file '/no-such-file'");
// OpenSSL errors. // OpenSSL errors.
exps.addThrow("No such file or directory"); exps.addThrow("No such file or directory");
exps.addThrow("No such file or directory (system library)"); exps.addThrow("No such file or directory (system library)");
@ -655,6 +658,9 @@ TEST_F(TLSTest, loadCertKeyFile) {
string botan_error = "PKCS #8 private key decoding failed with PKCS #8: "; string botan_error = "PKCS #8 private key decoding failed with PKCS #8: ";
botan_error += "Unknown PEM label CERTIFICATE"; botan_error += "Unknown PEM label CERTIFICATE";
exps.addThrow(botan_error); exps.addThrow(botan_error);
botan_error = "PKCS #8 private key decoding failed with PKCS #8: ";
botan_error += "Unknown PEM label 'CERTIFICATE'";
exps.addThrow(botan_error);
// OpenSSL errors. // OpenSSL errors.
exps.addThrow("no start line"); exps.addThrow("no start line");
exps.addThrow("no start line (PEM routines)"); exps.addThrow("no start line (PEM routines)");
@ -733,6 +739,8 @@ TEST_F(TLSTest, configureError) {
// Botan error. // Botan error.
string botan_error = "I/O error: DataSource: Failure opening file /no-such-file"; string botan_error = "I/O error: DataSource: Failure opening file /no-such-file";
exps.addThrow(common_error + botan_error); exps.addThrow(common_error + botan_error);
botan_error = "I/O error: DataSource: Failure opening file '/no-such-file'";
exps.addThrow(common_error + botan_error);
// OpenSSL errors. // OpenSSL errors.
string openssl_error = "No such file or directory"; string openssl_error = "No such file or directory";
exps.addThrow(common_error + openssl_error); exps.addThrow(common_error + openssl_error);
@ -946,6 +954,7 @@ TEST_F(TLSTest, serverNotConfigured) {
exps.clear(); exps.clear();
// On Botan and some OpenSSL the client hangs. // On Botan and some OpenSSL the client hangs.
exps.addTimeout(); exps.addTimeout();
exps.addError("handshake_failure");
// OpenSSL errors. // OpenSSL errors.
exps.addError("sslv3 alert handshake failure"); exps.addError("sslv3 alert handshake failure");
exps.addError("sslv3 alert handshake failure (SSL routines)"); exps.addError("sslv3 alert handshake failure (SSL routines)");
@ -1027,6 +1036,7 @@ TEST_F(TLSTest, clientNotConfigured) {
Expecteds exps; Expecteds exps;
// On Botan and some OpenSSL the server hangs. // On Botan and some OpenSSL the server hangs.
exps.addTimeout(); exps.addTimeout();
exps.addError("bad_certificate");
// OpenSSL errors. // OpenSSL errors.
exps.addError("tlsv1 alert unknown ca"); exps.addError("tlsv1 alert unknown ca");
exps.addError("tlsv1 alert unknown ca (SSL routines)"); exps.addError("tlsv1 alert unknown ca (SSL routines)");
@ -1128,6 +1138,7 @@ TEST_F(TLSTest, clientHTTPnoS) {
exps.addTimeout(); exps.addTimeout();
// Botan error. // Botan error.
exps.addError("protocol_version"); exps.addError("protocol_version");
exps.addError("unexpected_message");
// Old LibreSSL error. // Old LibreSSL error.
exps.addError("tlsv1 alert protocol version"); exps.addError("tlsv1 alert protocol version");
// OpenSSL errors (OpenSSL recognizes HTTP). // OpenSSL errors (OpenSSL recognizes HTTP).
@ -1220,6 +1231,7 @@ TEST_F(TLSTest, unknownClient) {
// Botan errors. // Botan errors.
exps.addError("record_overflow"); exps.addError("record_overflow");
exps.addError("protocol_version"); exps.addError("protocol_version");
exps.addError("unexpected_message");
// Old LibreSSL error. // Old LibreSSL error.
exps.addError("tlsv1 alert protocol version"); exps.addError("tlsv1 alert protocol version");
// Old OpenSSL error. // Old OpenSSL error.
@ -1630,6 +1642,7 @@ TEST_F(TLSTest, serverNotConfiguredCloseonError) {
exps.clear(); exps.clear();
// Botan and some OpenSSL. // Botan and some OpenSSL.
exps.addError("stream truncated"); exps.addError("stream truncated");
exps.addError("handshake_failure");
// Alias on old OpenSSL. // Alias on old OpenSSL.
exps.addError("short read"); exps.addError("short read");
// OpenSSL errors. // OpenSSL errors.
@ -1710,6 +1723,7 @@ TEST_F(TLSTest, clientNotConfiguredCloseonError) {
Expecteds exps; Expecteds exps;
// Botan and some OpenSSL. // Botan and some OpenSSL.
exps.addError("stream truncated"); exps.addError("stream truncated");
exps.addError("bad_certificate");
// Alias on old OpenSSL. // Alias on old OpenSSL.
exps.addError("short read"); exps.addError("short read");
// OpenSSL errors. // OpenSSL errors.
@ -1810,6 +1824,7 @@ TEST_F(TLSTest, clientHTTPnoSCloseonError) {
exps.addTimeout(); exps.addTimeout();
// Botan behavior was reported and fixed. // Botan behavior was reported and fixed.
exps.addError("protocol_version"); exps.addError("protocol_version");
exps.addError("unexpected_message");
// Old LibreSSL error. // Old LibreSSL error.
exps.addError("tlsv1 alert protocol version"); exps.addError("tlsv1 alert protocol version");
// OpenSSL errors when OpenSSL recognizes HTTP. // OpenSSL errors when OpenSSL recognizes HTTP.

View File

@ -21,6 +21,9 @@
#include <botan/certstor_flatfile.h> #include <botan/certstor_flatfile.h>
#include <botan/pkcs8.h> #include <botan/pkcs8.h>
#include <botan/auto_rng.h> #include <botan/auto_rng.h>
#if BOTAN_VERSION_MAJOR > 2
#include <botan/tls_session_manager_noop.h>
#endif
inline std::string CA_(const std::string& filename) { inline std::string CA_(const std::string& filename) {
return (std::string(TEST_CA_DIR) + "/" + filename); return (std::string(TEST_CA_DIR) + "/" + filename);
@ -35,19 +38,29 @@ using Client_Certificate_Store = Botan::Flatfile_Certificate_Store;
class Client_Credentials_Manager : public Botan::Credentials_Manager class Client_Credentials_Manager : public Botan::Credentials_Manager
{ {
public: public:
#if BOTAN_VERSION_MAJOR > 2
explicit Client_Credentials_Manager()
#else
explicit Client_Credentials_Manager(Botan::RandomNumberGenerator& rng) explicit Client_Credentials_Manager(Botan::RandomNumberGenerator& rng)
#endif
: stores_(), certs_(), : stores_(), certs_(),
store_(new Client_Certificate_Store(CA_("kea-ca.crt"))), store_(new Client_Certificate_Store(CA_("kea-ca.crt"))),
cert_(Botan::X509_Certificate(CA_("kea-client.crt"))), cert_(Botan::X509_Certificate(CA_("kea-client.crt"))),
key_(Botan::PKCS8::load_key(CA_("kea-client.key"), rng)) key_()
{ {
#if BOTAN_VERSION_MAJOR > 2
Botan::DataSource_Stream source(CA_("kea-client.key"));
auto priv_key = Botan::PKCS8::load_key(source);
key_ = std::move(priv_key);
#else
auto priv_key = Botan::PKCS8::load_key(CA_("kea-client.key"), rng);
key_.reset(priv_key);
#endif
stores_.push_back(store_.get()); stores_.push_back(store_.get());
certs_.push_back(cert_); certs_.push_back(cert_);
} }
virtual ~Client_Credentials_Manager() virtual ~Client_Credentials_Manager() = default;
{
}
std::vector<Botan::Certificate_Store*> std::vector<Botan::Certificate_Store*>
trusted_certificate_authorities(const std::string&, trusted_certificate_authorities(const std::string&,
@ -58,25 +71,36 @@ public:
std::vector<Botan::X509_Certificate> std::vector<Botan::X509_Certificate>
cert_chain(const std::vector<std::string>&, cert_chain(const std::vector<std::string>&,
#if BOTAN_VERSION_MAJOR > 2
const std::vector<Botan::AlgorithmIdentifier>&,
#endif
const std::string&, const std::string&,
const std::string&) override const std::string&) override
{ {
return certs_; return certs_;
} }
Botan::Private_Key* #if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::Private_Key>
#else
Botan::Private_Key*
#endif
private_key_for(const Botan::X509_Certificate&, private_key_for(const Botan::X509_Certificate&,
const std::string&, const std::string&,
const std::string&) override const std::string&) override
{ {
return key_.get(); #if BOTAN_VERSION_MAJOR > 2
return (key_);
#else
return (key_.get());
#endif
} }
std::vector<Botan::Certificate_Store*> stores_; std::vector<Botan::Certificate_Store*> stores_;
std::vector<Botan::X509_Certificate> certs_; std::vector<Botan::X509_Certificate> certs_;
std::shared_ptr<Botan::Certificate_Store> store_; std::shared_ptr<Botan::Certificate_Store> store_;
Botan::X509_Certificate cert_; Botan::X509_Certificate cert_;
std::unique_ptr<Botan::Private_Key> key_; std::shared_ptr<Botan::Private_Key> key_;
}; };
using Client_Session_Manager = Botan::TLS::Session_Manager_Noop; using Client_Session_Manager = Botan::TLS::Session_Manager_Noop;
@ -101,8 +125,12 @@ public:
class client class client
{ {
public: public:
client(boost::asio::io_context& io_context, client(boost::asio::io_service& io_context,
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::TLS::Context> context,
#else
Botan::TLS::Context& context, Botan::TLS::Context& context,
#endif
const tcp::endpoint& endpoint) const tcp::endpoint& endpoint)
: socket_(io_context, context) : socket_(io_context, context)
{ {
@ -128,7 +156,11 @@ private:
void handshake() void handshake()
{ {
#if BOTAN_VERSION_MAJOR > 2
socket_.async_handshake(Botan::TLS::Connection_Side::Client,
#else
socket_.async_handshake(Botan::TLS::Connection_Side::CLIENT, socket_.async_handshake(Botan::TLS::Connection_Side::CLIENT,
#endif
[this](const boost::system::error_code& error) [this](const boost::system::error_code& error)
{ {
if (!error) if (!error)
@ -210,11 +242,24 @@ int main(int argc, char* argv[])
using namespace std; // For atoi. using namespace std; // For atoi.
tcp::endpoint endpoint( tcp::endpoint endpoint(
boost::asio::ip::make_address(argv[1]), atoi(argv[2])); boost::asio::ip::make_address(argv[1]), atoi(argv[2]));
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::AutoSeeded_RNG>
rng(new Botan::AutoSeeded_RNG());
std::shared_ptr<Client_Credentials_Manager>
creds_mgr(new Client_Credentials_Manager());
std::shared_ptr<Client_Session_Manager>
sess_mgr(new Client_Session_Manager());
std::shared_ptr<Client_Policy>
policy(new Client_Policy());
std::shared_ptr<Botan::TLS::Context>
ctx(new Botan::TLS::Context(creds_mgr, rng, sess_mgr, policy));
#else
Botan::AutoSeeded_RNG rng; Botan::AutoSeeded_RNG rng;
Client_Credentials_Manager creds_mgr(rng); Client_Credentials_Manager creds_mgr(rng);
Client_Session_Manager sess_mgr; Client_Session_Manager sess_mgr;
Client_Policy policy; Client_Policy policy;
Botan::TLS::Context ctx(creds_mgr, rng, sess_mgr, policy); Botan::TLS::Context ctx(creds_mgr, rng, sess_mgr, policy);
#endif
client c(io_context, ctx, endpoint); client c(io_context, ctx, endpoint);

View File

@ -20,6 +20,9 @@
#include <botan/certstor_flatfile.h> #include <botan/certstor_flatfile.h>
#include <botan/pkcs8.h> #include <botan/pkcs8.h>
#include <botan/auto_rng.h> #include <botan/auto_rng.h>
#if BOTAN_VERSION_MAJOR > 2
#include <botan/tls_session_manager_noop.h>
#endif
inline std::string CA_(const std::string& filename) { inline std::string CA_(const std::string& filename) {
return (std::string(TEST_CA_DIR) + "/" + filename); return (std::string(TEST_CA_DIR) + "/" + filename);
@ -32,19 +35,29 @@ using Server_Certificate_Store = Botan::Flatfile_Certificate_Store;
class Server_Credentials_Manager : public Botan::Credentials_Manager class Server_Credentials_Manager : public Botan::Credentials_Manager
{ {
public: public:
#if BOTAN_VERSION_MAJOR > 2
explicit Server_Credentials_Manager()
#else
explicit Server_Credentials_Manager(Botan::RandomNumberGenerator& rng) explicit Server_Credentials_Manager(Botan::RandomNumberGenerator& rng)
#endif
: stores_(), certs_(), : stores_(), certs_(),
store_(new Server_Certificate_Store(CA_("kea-ca.crt"))), store_(new Server_Certificate_Store(CA_("kea-ca.crt"))),
cert_(Botan::X509_Certificate(CA_("kea-server.crt"))), cert_(Botan::X509_Certificate(CA_("kea-server.crt"))),
key_(Botan::PKCS8::load_key(CA_("kea-server.key"), rng)) key_()
{ {
#if BOTAN_VERSION_MAJOR > 2
Botan::DataSource_Stream source(CA_("kea-server.key"));
auto priv_key = Botan::PKCS8::load_key(source);
key_ = std::move(priv_key);
#else
auto priv_key = Botan::PKCS8::load_key(CA_("kea-server.key"), rng);
key_.reset(priv_key);
#endif
stores_.push_back(store_.get()); stores_.push_back(store_.get());
certs_.push_back(cert_); certs_.push_back(cert_);
} }
virtual ~Server_Credentials_Manager() virtual ~Server_Credentials_Manager() = default;
{
}
std::vector<Botan::Certificate_Store*> std::vector<Botan::Certificate_Store*>
trusted_certificate_authorities(const std::string&, trusted_certificate_authorities(const std::string&,
@ -55,25 +68,36 @@ public:
std::vector<Botan::X509_Certificate> std::vector<Botan::X509_Certificate>
cert_chain(const std::vector<std::string>&, cert_chain(const std::vector<std::string>&,
#if BOTAN_VERSION_MAJOR > 2
const std::vector<Botan::AlgorithmIdentifier>&,
#endif
const std::string&, const std::string&,
const std::string&) override const std::string&) override
{ {
return certs_; return certs_;
} }
Botan::Private_Key* #if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::Private_Key>
#else
Botan::Private_Key*
#endif
private_key_for(const Botan::X509_Certificate&, private_key_for(const Botan::X509_Certificate&,
const std::string&, const std::string&,
const std::string&) override const std::string&) override
{ {
return key_.get(); #if BOTAN_VERSION_MAJOR > 2
return (key_);
#else
return (key_.get());
#endif
} }
std::vector<Botan::Certificate_Store*> stores_; std::vector<Botan::Certificate_Store*> stores_;
std::vector<Botan::X509_Certificate> certs_; std::vector<Botan::X509_Certificate> certs_;
std::shared_ptr<Botan::Certificate_Store> store_; std::shared_ptr<Botan::Certificate_Store> store_;
Botan::X509_Certificate cert_; Botan::X509_Certificate cert_;
std::unique_ptr<Botan::Private_Key> key_; std::shared_ptr<Botan::Private_Key> key_;
}; };
using Server_Session_Manager = Botan::TLS::Session_Manager_Noop; using Server_Session_Manager = Botan::TLS::Session_Manager_Noop;
@ -98,7 +122,11 @@ public:
class session : public std::enable_shared_from_this<session> class session : public std::enable_shared_from_this<session>
{ {
public: public:
#if BOTAN_VERSION_MAJOR > 2
session(tcp::socket socket, std::shared_ptr<Botan::TLS::Context> ctx)
#else
session(tcp::socket socket, Botan::TLS::Context& ctx) session(tcp::socket socket, Botan::TLS::Context& ctx)
#endif
: socket_(std::move(socket), ctx) : socket_(std::move(socket), ctx)
{ {
} }
@ -112,7 +140,11 @@ private:
void do_handshake() void do_handshake()
{ {
auto self(shared_from_this()); auto self(shared_from_this());
#if BOTAN_VERSION_MAJOR > 2
socket_.async_handshake(Botan::TLS::Connection_Side::Server,
#else
socket_.async_handshake(Botan::TLS::Connection_Side::SERVER, socket_.async_handshake(Botan::TLS::Connection_Side::SERVER,
#endif
[this, self](const boost::system::error_code& error) [this, self](const boost::system::error_code& error)
{ {
if (!error) if (!error)
@ -162,12 +194,24 @@ class server
public: public:
server(boost::asio::io_context& io_context, server(boost::asio::io_context& io_context,
unsigned short port, unsigned short port,
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::Credentials_Manager> creds_mgr,
std::shared_ptr<Botan::RandomNumberGenerator> rng,
std::shared_ptr<Botan::TLS::Session_Manager> sess_mgr,
std::shared_ptr<Botan::TLS::Policy> policy
#else
Botan::Credentials_Manager& creds_mgr, Botan::Credentials_Manager& creds_mgr,
Botan::RandomNumberGenerator& rng, Botan::RandomNumberGenerator& rng,
Botan::TLS::Session_Manager& sess_mgr, Botan::TLS::Session_Manager& sess_mgr,
Botan::TLS::Policy& policy) Botan::TLS::Policy& policy
#endif
)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)),
#if BOTAN_VERSION_MAJOR > 2
context_(new Botan::TLS::Context(creds_mgr, rng, sess_mgr, policy))
#else
context_(creds_mgr, rng, sess_mgr, policy) context_(creds_mgr, rng, sess_mgr, policy)
#endif
{ {
do_accept(); do_accept();
} }
@ -188,7 +232,11 @@ private:
} }
tcp::acceptor acceptor_; tcp::acceptor acceptor_;
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::TLS::Context> context_;
#else
Botan::TLS::Context context_; Botan::TLS::Context context_;
#endif
}; };
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -203,10 +251,21 @@ int main(int argc, char* argv[])
boost::asio::io_context io_context; boost::asio::io_context io_context;
#if BOTAN_VERSION_MAJOR > 2
std::shared_ptr<Botan::AutoSeeded_RNG>
rng(new Botan::AutoSeeded_RNG());
std::shared_ptr<Server_Credentials_Manager>
creds_mgr(new Server_Credentials_Manager());
std::shared_ptr<Server_Session_Manager>
sess_mgr(new Server_Session_Manager());
std::shared_ptr<Server_Policy>
policy(new Server_Policy());
#else
Botan::AutoSeeded_RNG rng; Botan::AutoSeeded_RNG rng;
Server_Credentials_Manager creds_mgr(rng); Server_Credentials_Manager creds_mgr(rng);
Server_Session_Manager sess_mgr; Server_Session_Manager sess_mgr;
Server_Policy policy; Server_Policy policy;
#endif
server s(io_context, std::atoi(argv[1]), creds_mgr, rng, sess_mgr, policy); server s(io_context, std::atoi(argv[1]), creds_mgr, rng, sess_mgr, policy);
io_context.run(); io_context.run();