Commit e176afe2 authored by Vladimir Bashkirtsev's avatar Vladimir Bashkirtsev

Fixed gu_asio_test

parent fd8c195a
all: all:
tar xf galera-26.4.8.tar.gz tar xf galera-26.4.8.tar.gz
patch -Np1 -d galera-26.4.8 < galera-26.4.8-fix_certs.patch
patch -Np1 -d galera-26.4.8 < galera-26.4.8-fix_test_ssl_certificate_chain.patch
cd galera-26.4.8 && HOME=/root CK_TIMEOUT_MULTIPLIER=30 ./scripts/build.sh cd galera-26.4.8 && HOME=/root CK_TIMEOUT_MULTIPLIER=30 ./scripts/build.sh
cp galera-26.4.8/libgalera_smm.so /usr/lib cp galera-26.4.8/libgalera_smm.so /usr/lib
rm -rf galera-26.4.8 rm -rf galera-26.4.8
diff -uNr galera-26.4.8/galerautils/tests/CMakeLists.txt galera-26.4.8-fix_certs/galerautils/tests/CMakeLists.txt
--- galera-26.4.8/galerautils/tests/CMakeLists.txt 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_certs/galerautils/tests/CMakeLists.txt 2024-04-19 14:53:38.246960082 +0930
@@ -45,7 +45,6 @@
#
# C++ galerautils tests.
#
-
add_executable(gu_tests++
gu_atomic_test.cpp
gu_gtid_test.cpp
@@ -71,7 +70,7 @@
target_compile_definitions(gu_tests++
PRIVATE
- -DGU_ASIO_TEST_CERT_DIR="${CMAKE_SOURCE_DIR}/tests/conf")
+ -DGU_ASIO_TEST_CERT_DIR="${CMAKE_CURRENT_BINARY_DIR}/certs")
# TODO: These should be eventually fixed.
target_compile_options(gu_tests++
@@ -89,7 +88,6 @@
NAME gu_tests++
COMMAND gu_tests++
)
-
#
# Deqmap micro benchmark.
#
diff -uNr galera-26.4.8/galerautils/tests/gu_asio_test.cpp galera-26.4.8-fix_certs/galerautils/tests/gu_asio_test.cpp
--- galera-26.4.8/galerautils/tests/gu_asio_test.cpp 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_certs/galerautils/tests/gu_asio_test.cpp 2024-04-19 14:51:22.194740597 +0930
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019-2020 Codership Oy <info@codership.com>
+ * Copyright (C) 2019-2023 Codership Oy <info@codership.com>
*/
@@ -897,18 +897,276 @@
#ifdef GALERA_HAVE_SSL
+#include <openssl/bn.h>
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
#include <signal.h>
-//
-// SSL
-//
+#include <vector>
static std::string get_cert_dir()
{
- // This will be set by CMake/preprocessor.
+ static_assert(::strlen(GU_ASIO_TEST_CERT_DIR) > 0);
+ const std::string ret{ GU_ASIO_TEST_CERT_DIR };
+ auto* dir = opendir(ret.c_str());
+ if (!dir)
+ {
+ if (mkdir(ret.c_str(), S_IRWXU))
+ {
+ const auto* errstr = ::strerror(errno);
+ gu_throw_fatal << "Could not create dir " << ret << ": " << errstr;
+ }
+ }
+ else
+ {
+ closedir(dir);
+ }
return GU_ASIO_TEST_CERT_DIR;
}
+static int password_cb(char*, int, int, void*) { return 0; }
+
+static void throw_error(const char* msg)
+{
+ gu_throw_fatal << msg << ": " << ERR_error_string(ERR_get_error(), nullptr);
+}
+
+static EVP_PKEY* create_key()
+{
+#if OPENSSL_VERSION_MAJOR < 3
+ auto* bn = BN_new();
+ if (!bn)
+ {
+ throw_error("could not create BN");
+ }
+ BN_set_word(bn, 0x10001);
+ auto* rsa = RSA_new();
+ if (!rsa)
+ {
+ BN_free(bn);
+ throw_error("could not create RSA");
+ }
+ RSA_generate_key_ex(rsa, 2048, bn, nullptr);
+ auto* pkey = EVP_PKEY_new();
+ if (!pkey)
+ {
+ BN_free(bn);
+ RSA_free(rsa);
+ throw_error("could not create PKEY");
+ }
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ RSA_free(rsa);
+ BN_free(bn);
+ return pkey;
+#else
+ auto* ret = EVP_RSA_gen(2048);
+ if (!ret)
+ {
+ throw_error("could not create RSA");
+ }
+ return ret;
+#endif /* OPENSSL_VERSION_MAJOR < 3 */
+}
+
+static FILE* open_file(const std::string& path, const char* mode)
+{
+ auto* ret = fopen(path.c_str(), mode);
+ if (!ret)
+ {
+ const auto* errstr = ::strerror(errno);
+ gu_throw_fatal << "Could not open file " << path << ": "
+ << errstr;
+ }
+ return ret;
+}
+
+static void write_key(EVP_PKEY* pkey, const std::string& filename)
+{
+ const std::string cert_dir = get_cert_dir();
+ const std::string key_file_path = cert_dir + "/" + filename;
+ auto* key_file = open_file(key_file_path, "wb");
+ if (!PEM_write_PrivateKey(key_file, pkey, nullptr, nullptr, 0, password_cb,
+ nullptr))
+ {
+ throw_error("Could not write key");
+ }
+ fclose(key_file);
+}
+
+static void set_x509v3_extensions(X509* x509, X509* issuer)
+{
+ auto* conf_bio = BIO_new(BIO_s_mem());
+ std::string ext{ "[extensions]\n"
+ "authorityKeyIdentifier=keyid,issuer\n"
+ "subjectKeyIdentifier=hash\n" };
+ if (!issuer)
+ {
+ ext += "basicConstraints=critical,CA:TRUE\n";
+ }
+ else
+ {
+ ext += "keyUsage=digitalSignature,keyEncipherment\n";
+ ext += "basicConstraints=CA:FALSE\n";
+ }
+ BIO_printf(conf_bio, "%s", ext.c_str());
+ auto* conf = NCONF_new(nullptr);
+ long errorline = -1;
+ int err;
+ if ((err = NCONF_load_bio(conf, conf_bio, &errorline)) <= 0)
+ {
+ gu_throw_fatal << "Could not load conf: " << err;
+ }
+ if (errorline != -1)
+ {
+ gu_throw_fatal << "Could not load conf, errorline: " << errorline;
+ }
+ // TODO: V3 extensions
+ X509V3_CTX ctx;
+ X509V3_set_ctx(&ctx, issuer ? issuer : x509, x509, nullptr, nullptr, 0);
+ X509V3_set_nconf(&ctx, conf);
+ if (!X509V3_EXT_add_nconf(conf, &ctx, "extensions", x509))
+ {
+ throw_error("Could not add extension");
+ }
+ NCONF_free(conf);
+ BIO_free(conf_bio);
+}
+
+static X509* create_x509(EVP_PKEY* pkey, X509* issuer, const char* cn)
+{
+ auto* x509 = X509_new();
+ /* According to standard, value 2 means version 3. */
+ X509_set_version(x509, 2);
+ ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
+ X509_gmtime_adj(X509_get_notBefore(x509), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
+ X509_set_pubkey(x509, pkey);
+
+ auto* name = X509_get_subject_name(x509);
+ X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)"FI",
+ -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC,
+ (unsigned char*)"Uusimaa", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC,
+ (unsigned char*)"Helsinki", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
+ (unsigned char*)"Codership", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC,
+ (unsigned char*)"Galera Devel", -1, -1, 0);
+ X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)cn, -1,
+ -1, 0);
+ if (!issuer)
+ {
+ /* Self signed */
+ X509_set_issuer_name(x509, name);
+ }
+ else
+ {
+ X509_set_issuer_name(x509, X509_get_subject_name(issuer));
+ }
+
+ set_x509v3_extensions(x509, issuer);
+
+ X509_sign(x509, pkey, EVP_sha256());
+
+ return x509;
+}
+
+static void write_x509(X509* x509, const std::string& filename)
+{
+ const std::string cert_dir = get_cert_dir();
+ const std::string file_path = cert_dir + "/" + filename;
+ auto* file = open_file(file_path, "wb");
+ if (!PEM_write_X509(file, x509))
+ {
+ throw_error("Could not write x509");
+ }
+ fclose(file);
+}
+
+static void write_x509_list(const std::vector<X509*>& certs,
+ const std::string& filename)
+{
+ const std::string cert_dir = get_cert_dir();
+ const std::string file_path = cert_dir + "/" + filename;
+ auto* file = open_file(file_path, "wb");
+ for (auto* x509 : certs)
+ {
+ if (!PEM_write_X509(file, x509))
+ {
+ throw_error("Could not write x509");
+ }
+ }
+ fclose(file);
+}
+
+/* Self signed CA + certificate */
+static void generate_self_signed()
+{
+ auto* pkey = create_key();
+ write_key(pkey, "galera_key.pem");
+ auto* ca = create_x509(pkey, nullptr, "Galera Root");
+ write_x509(ca, "galera_ca.pem");
+
+ auto* cert = create_x509(pkey, ca, "Galera Cert");
+ write_x509(cert, "galera_cert.pem");
+ X509_free(cert);
+ X509_free(ca);
+ EVP_PKEY_free(pkey);
+}
+
+/*
+ ---- Server cert 1
+ /
+ Root CA - Intermediate CA
+ \---- Server cert 2
+
+ Two bundles consisting of intermediate CA and server certificate
+ are created for servers 1 and 2.
+ */
+static void generate_chains()
+{
+ auto* root_ca_key = create_key();
+ auto* root_ca = create_x509(root_ca_key, nullptr, "Galera Root CA");
+ auto* int_ca_key = create_key();
+ auto* int_ca = create_x509(int_ca_key, root_ca, "Galera Intermediate CA");
+
+ auto* server_1_key = create_key();
+ auto* server_1_cert = create_x509(server_1_key, int_ca, "Galera Server 1");
+ auto* server_2_key = create_key();
+ auto* server_2_cert = create_x509(server_2_key, int_ca, "Galera Server 2");
+
+ write_x509(root_ca, "galera-ca.pem");
+ write_key(server_1_key, "galera-server-1.key");
+ write_x509_list({ server_1_cert, int_ca }, "bundle-galera-server-1.pem");
+ write_key(server_2_key, "galera-server-2.key");
+ write_x509_list({ server_2_cert, int_ca }, "bundle-galera-server-2.pem");
+
+ X509_free(server_2_cert);
+ EVP_PKEY_free(server_2_key);
+ X509_free(server_1_cert);
+ EVP_PKEY_free(server_1_key);
+ X509_free(int_ca);
+ EVP_PKEY_free(int_ca_key);
+ X509_free(root_ca);
+ EVP_PKEY_free(root_ca_key);
+}
+
+static void generate_certificates()
+{
+ generate_self_signed();
+ generate_chains();
+}
+
+//
+// SSL
+//
+
static gu::Config get_ssl_config()
{
gu::Config ret;
@@ -2092,6 +2350,7 @@
//
// SSL
//
+ generate_certificates();
tc = tcase_create("test_ssl_io_service");
tcase_add_test(tc, test_ssl_io_service);
diff -uNr galera-26.4.8/.gitignore galera-26.4.8-fix_certs/.gitignore
--- galera-26.4.8/.gitignore 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_certs/.gitignore 2024-04-19 14:51:22.187740740 +0930
@@ -18,6 +18,7 @@
galera/tests/galera_check.passed
galerautils/src/gu_fnv_bench
galerautils/tests/gu_tests
+galerautils/tests/certs
galerautils/tests/gu_tests++
galerautils/tests/gu_tests++.passed
galerautils/tests/gu_tests.passed
diff -uNr galera-26.4.8/galerautils/src/gu_asio.cpp galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/src/gu_asio.cpp
--- galera-26.4.8/galerautils/src/gu_asio.cpp 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/src/gu_asio.cpp 2024-04-20 17:50:03.402012015 +0930
@@ -695,6 +695,11 @@
impl_->native().run_one();
}
+void gu::AsioIoService::poll_one()
+{
+ impl_->native().poll_one();
+}
+
void gu::AsioIoService::run()
{
impl_->native().run();
diff -uNr galera-26.4.8/galerautils/src/gu_asio.hpp galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/src/gu_asio.hpp
--- galera-26.4.8/galerautils/src/gu_asio.hpp 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/src/gu_asio.hpp 2024-04-20 17:49:09.115121259 +0930
@@ -662,6 +662,12 @@
void run_one();
/**
+ * Run at most one IO service handler, return immediately
+ * if no handlers are ready to run.
+ */
+ void poll_one();
+
+ /**
* Run until IO service is stopped or runs out of work.
*/
void run();
diff -uNr galera-26.4.8/galerautils/tests/gu_asio_test.cpp galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/tests/gu_asio_test.cpp
--- galera-26.4.8/galerautils/tests/gu_asio_test.cpp 2021-04-08 15:35:44.000000000 +0930
+++ galera-26.4.8-fix_test_ssl_certificate_chain/galerautils/tests/gu_asio_test.cpp 2024-04-20 18:00:41.053982236 +0930
@@ -1174,8 +1174,13 @@
client_io_service.run_one(); // Process async connect
server_io_service.run_one(); // Accept
client_io_service.run_one(); // Client hello
- server_io_service.run_one(); // Server handles
- ck_assert(acceptor_handler->accepted_socket() != 0);
+ client_io_service.run_one(); // Client hello IO completion
+ // server_io_service.run_one(); // Server handles
+ while (acceptor_handler->accepted_socket() != 0)
+ {
+ client_io_service.poll_one();
+ server_io_service.poll_one();
+ }
}
END_TEST
@@ -1201,7 +1206,13 @@
client_io_service.run_one(); // Process async connect
server_io_service.run_one(); // Accept
client_io_service.run_one(); // Client hello
- server_io_service.run_one(); // Server handles
+ client_io_service.run_one(); // Client hello IO completion
+ // server_io_service.run_one(); // Server handles
+ while (not handler->last_error_code())
+ {
+ client_io_service.poll_one();
+ server_io_service.poll_one();
+ }
ck_assert(not acceptor_handler->accepted_socket());
ck_assert_msg(handler->last_error_code().message().find(
"unable to get local issuer certificate") !=
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment