diff --git a/builder-support/specs/wforce.spec b/builder-support/specs/wforce.spec index 7a857267..4bb33705 100644 --- a/builder-support/specs/wforce.spec +++ b/builder-support/specs/wforce.spec @@ -91,6 +91,7 @@ Summary: Longterm abuse data reporting and alerter %build %{?scl: %{scl} - << \EOF} %configure \ + CXXFLAGS="%{optflags} -Wno-enum-constexpr-conversion" \ --disable-dependency-tracking \ --docdir=%{_docdir}/%{name}-%{getenv:BUILDER_VERSION} \ --disable-static --with-luajit --sysconfdir=/etc/%{name} \ diff --git a/common/Makefile.am b/common/Makefile.am index 59f82cae..6d87dcb4 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -100,7 +100,8 @@ endif testrunner_SOURCES = \ testrunner.cc \ test-minicurl.cc \ - test-serialize.cc + test-serialize.cc \ + test-crypto.cc EXTRA_testrunner_DEPENDENCIES = \ $(EXT_LIBS) libweakforce.la diff --git a/common/sodcrypto.cc b/common/sodcrypto.cc index 573e499a..5c67da85 100644 --- a/common/sodcrypto.cc +++ b/common/sodcrypto.cc @@ -29,34 +29,42 @@ #ifdef HAVE_LIBSODIUM +string newKeyStr() +{ + string key; + key.resize(crypto_secretbox_KEYBYTES); + randombytes_buf(key.data(), crypto_secretbox_KEYBYTES); + return key; +} + string newKey() { - unsigned char key[crypto_secretbox_KEYBYTES]; - randombytes_buf(key, sizeof key); - return "\""+Base64Encode(string((char*)key, sizeof key))+"\""; + return "\""+Base64Encode(newKeyStr())+"\""; } std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce) { - unsigned char ciphertext[msg.length() + crypto_secretbox_MACBYTES]; - crypto_secretbox_easy(ciphertext, (unsigned char*)msg.c_str(), msg.length(), nonce.value, (unsigned char*)key.c_str()); + std::string ciphertext; + ciphertext.resize(msg.length() + crypto_secretbox_MACBYTES); + crypto_secretbox_easy((unsigned char*)ciphertext.data(), (unsigned char*)msg.c_str(), msg.length(), nonce.value, (unsigned char*)key.c_str()); nonce.increment(); - return string((char*)ciphertext, sizeof(ciphertext)); + return ciphertext; } std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce) { + std::string decrypted; // It's fine if there's no data to decrypt if ((msg.length() - crypto_secretbox_MACBYTES) > 0) { - unsigned char decrypted[msg.length() - crypto_secretbox_MACBYTES]; + decrypted.resize(msg.length() - crypto_secretbox_MACBYTES); - if (crypto_secretbox_open_easy(decrypted, (const unsigned char*)msg.c_str(), + if (crypto_secretbox_open_easy((unsigned char*)decrypted.data(), (const unsigned char*)msg.c_str(), msg.length(), nonce.value, (const unsigned char*)key.c_str()) != 0) { throw std::runtime_error("Could not decrypt message"); } nonce.increment(); - return string((char*)decrypted, sizeof(decrypted)); + return decrypted; } else { nonce.increment(); @@ -67,22 +75,28 @@ std::string sodDecryptSym(const std::string& msg, const std::string& key, Sodium #define POLY1305_BLOCK_SIZE 16 -string newKey() +string newKeyStr() { - unsigned char key[CHACHA20_POLY1305_KEY_SIZE]; - if (RAND_priv_bytes(key, sizeof key) != 1) { + string key; + key.resize(CHACHA20_POLY1305_KEY_SIZE); + if (RAND_priv_bytes((unsigned char*)key.data(), CHACHA20_POLY1305_KEY_SIZE) != 1) { throw std::runtime_error( "Could not initialize random number generator for cryptographic functions - this is not recoverable"); } - return "\"" + Base64Encode(string((char*) key, sizeof key)) + "\""; + return key; +} + +string newKey() +{ + return "\"" + Base64Encode(newKeyStr()) + "\""; } std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce) { - unsigned char ciphertext[msg.length() + POLY1305_BLOCK_SIZE]; + std::string ciphertext; + ciphertext.resize(msg.length() + POLY1305_BLOCK_SIZE); int len; - int ciphertext_len; // Each thread gets its own cipher context static thread_local auto ctx = std::unique_ptr(nullptr, EVP_CIPHER_CTX_free); @@ -105,26 +119,24 @@ std::string sodEncryptSym(const std::string& msg, const std::string& key, Sodium throw std::runtime_error("sodEncryptSym: EVP_EncryptInit_ex() could not initialize encryption key and IV"); if (1 != - EVP_EncryptUpdate(ctx.get(), ciphertext + POLY1305_BLOCK_SIZE, &len, (unsigned char*) msg.c_str(), msg.length())) + EVP_EncryptUpdate(ctx.get(), (unsigned char*)ciphertext.data() + POLY1305_BLOCK_SIZE, &len, (unsigned char*) msg.c_str(), msg.length())) throw std::runtime_error("sodEncryptSym: EVP_EncryptUpdate() could not encrypt message"); - ciphertext_len = len; - if (1 != EVP_EncryptFinal_ex(ctx.get(), ciphertext + len + POLY1305_BLOCK_SIZE, &len)) + if (1 != EVP_EncryptFinal_ex(ctx.get(), (unsigned char*)ciphertext.data() + len + POLY1305_BLOCK_SIZE, &len)) throw std::runtime_error("sodEncryptSym: EVP_EncryptFinal_ex() could finalize message encryption");; - ciphertext_len += len; /* Get the tag */ - if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG, POLY1305_BLOCK_SIZE, ciphertext)) + if (1 != EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG, POLY1305_BLOCK_SIZE, ciphertext.data())) throw std::runtime_error("sodEncryptSym: EVP_CIPHER_CTX_ctrl() could not get tag"); nonce.increment(); - return string((char*) ciphertext, sizeof(ciphertext)); + return ciphertext; } std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce) { + std::string plaintext; int len; - int plaintext_len; // Each thread gets its own cipher context static thread_local auto ctx = std::unique_ptr(nullptr, EVP_CIPHER_CTX_free); @@ -137,7 +149,7 @@ std::string sodDecryptSym(const std::string& msg, const std::string& key, Sodium if ((msg.length() - POLY1305_BLOCK_SIZE) > 0) { string tag = msg.substr(0, POLY1305_BLOCK_SIZE); - char plaintext[msg.length() - POLY1305_BLOCK_SIZE]; + plaintext.resize(msg.length() - POLY1305_BLOCK_SIZE); if (ctx.get() == nullptr) { if (!(ctx = std::unique_ptr(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free))) @@ -150,21 +162,20 @@ std::string sodDecryptSym(const std::string& msg, const std::string& key, Sodium if (1 != EVP_DecryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*) key.c_str(), nonce.value)) throw std::runtime_error("sodDecryptSym: EVP_DecryptInit_ex() could not initialize decryption key and IV"); - if (!EVP_DecryptUpdate(ctx.get(), (unsigned char*) plaintext, &len, + if (!EVP_DecryptUpdate(ctx.get(), (unsigned char*) plaintext.data(), &len, (unsigned char*) (msg.c_str() + POLY1305_BLOCK_SIZE), msg.length() - POLY1305_BLOCK_SIZE)) throw std::runtime_error("sodDecryptSym: EVP_DecryptUpdate() could not decrypt message"); - plaintext_len = len; /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG, POLY1305_BLOCK_SIZE, (void*) tag.c_str())) throw std::runtime_error("sodDecryptSym: EVP_CIPHER_CTX_ctrl() AEAD tag could not be validated"); - if (!EVP_DecryptFinal_ex(ctx.get(), (unsigned char*) (plaintext + len), &len)) + if (!EVP_DecryptFinal_ex(ctx.get(), (unsigned char*) (plaintext.data() + len), &len)) throw std::runtime_error("sodDecryptSym: EVP_DecryptFinal_ex() failed - plaintext cannot be trusted"); nonce.increment(); - return string(plaintext, plaintext_len); + return plaintext; } else { nonce.increment(); diff --git a/common/sodcrypto.hh b/common/sodcrypto.hh index 6e82851b..d5292607 100644 --- a/common/sodcrypto.hh +++ b/common/sodcrypto.hh @@ -59,9 +59,9 @@ struct SodiumNonce *p=ntohl(count); } - string toString() const + std::string toString() const { - return string((const char*)value, sizeof value); + return std::string((const char*)value, sizeof value); } unsigned char value[CHACHA20_POLY1305_IV_SIZE]; @@ -91,15 +91,15 @@ struct SodiumNonce *p=ntohl(count); } - string toString() const + std::string toString() const { - return string((const char*)value, crypto_secretbox_NONCEBYTES); + return std::string((const char*)value, crypto_secretbox_NONCEBYTES); } unsigned char value[crypto_secretbox_NONCEBYTES]; }; #endif -std::string newKeypair(); +std::string newKeyStr(); std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce&); std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce&); std::string newKey(); diff --git a/common/test-crypto.cc b/common/test-crypto.cc new file mode 100644 index 00000000..8cbaa069 --- /dev/null +++ b/common/test-crypto.cc @@ -0,0 +1,25 @@ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "sodcrypto.hh" + +BOOST_AUTO_TEST_SUITE(test_crypto) + + BOOST_AUTO_TEST_CASE(test_symmetric) + { + std::string keyStr = newKeyStr(); + SodiumNonce wnonce, rnonce; + wnonce.init(); + memcpy((char*)&rnonce, wnonce.value, sizeof(rnonce.value)); + std::string ciphertext, plaintext; + std::string msg("Hello"); + ciphertext= sodEncryptSym(msg, keyStr, wnonce); + plaintext= sodDecryptSym(ciphertext, keyStr, rnonce); + BOOST_CHECK(plaintext == msg); + } + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/m4/boost.m4 b/m4/boost.m4 index 8755b4e4..973c447b 100644 --- a/m4/boost.m4 +++ b/m4/boost.m4 @@ -22,7 +22,7 @@ # along with this program. If not, see . m4_define([_BOOST_SERIAL], [m4_translit([ -# serial 34 +# serial 38 ], [# ], [])]) @@ -428,7 +428,7 @@ dnl until we succeed to link conftest.o in an executable. The problem is dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always dnl remove all the temporary files including conftest.o. So the trick here dnl is to temporarily change the value of ac_objext so that conftest.o is -dnl preserved across tests. This is obviously fragile and I will burn in +dnl preserved accross tests. This is obviously fragile and I will burn in dnl hell for not respecting Autoconf's documented interfaces, but in the dnl mean time, it optimizes the macro by a factor of 5 to 30. dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left @@ -496,7 +496,7 @@ dnl generated only once above (before we start the for loops). if test x"$Boost_lib" = xyes; then # Check or used cached result of whether or not using -R or # -rpath makes sense. Some implementations of ld, such as for - # Mac OS X, require -rpath but -R is the flag known to work on + # Mac OSX, require -rpath but -R is the flag known to work on # other systems. https://github.com/tsuna/boost.m4/issues/19 AC_CACHE_VAL([boost_cv_rpath_link_ldflag], [case $boost_ldpath in @@ -1615,7 +1615,14 @@ if test x$boost_cv_inc_path != xno; then # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines # the same defines as GCC's). for i in \ + "defined __clang__ && __clang_major__ == 18 && __clang_minor__ == 1 @ clang181" \ + "defined __clang__ && __clang_major__ == 17 && __clang_minor__ == 0 @ clang170" \ + "defined __clang__ && __clang_major__ == 16 && __clang_minor__ == 0 @ clang160" \ + "defined __clang__ && __clang_major__ == 15 && __clang_minor__ == 0 @ clang150" \ + "defined __clang__ && __clang_major__ == 14 && __clang_minor__ == 0 @ clang140" \ + "defined __clang__ && __clang_major__ == 13 && __clang_minor__ == 0 @ clang130" \ "defined __clang__ && __clang_major__ == 12 && __clang_minor__ == 0 @ clang120" \ + "defined __clang__ && __clang_major__ == 11 && __clang_minor__ == 1 @ clang111" \ "defined __clang__ && __clang_major__ == 11 && __clang_minor__ == 0 @ clang110" \ "defined __clang__ && __clang_major__ == 10 && __clang_minor__ == 0 @ clang100" \ "defined __clang__ && __clang_major__ == 9 && __clang_minor__ == 0 @ clang90" \ @@ -1627,10 +1634,38 @@ if test x$boost_cv_inc_path != xno; then "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 9 @ clang39" \ "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 8 @ clang38" \ "defined __clang__ && __clang_major__ == 3 && __clang_minor__ == 7 @ clang37" \ + _BOOST_mingw_test(13, 2) \ + _BOOST_gcc_test(13, 2) \ + _BOOST_mingw_test(13, 1) \ + _BOOST_gcc_test(13, 1) \ + _BOOST_mingw_test(12, 3) \ + _BOOST_gcc_test(12, 3) \ + _BOOST_mingw_test(12, 2) \ + _BOOST_gcc_test(12, 2) \ + _BOOST_mingw_test(12, 1) \ + _BOOST_gcc_test(12, 1) \ + _BOOST_mingw_test(11, 4) \ + _BOOST_gcc_test(11, 4) \ + _BOOST_mingw_test(11, 3) \ + _BOOST_gcc_test(11, 3) \ + _BOOST_mingw_test(11, 2) \ + _BOOST_gcc_test(11, 2) \ + _BOOST_mingw_test(11, 1) \ + _BOOST_gcc_test(11, 1) \ + _BOOST_mingw_test(10, 5) \ + _BOOST_gcc_test(10, 5) \ + _BOOST_mingw_test(10, 4) \ + _BOOST_gcc_test(10, 4) \ + _BOOST_mingw_test(10, 3) \ + _BOOST_gcc_test(10, 3) \ _BOOST_mingw_test(10, 2) \ _BOOST_gcc_test(10, 2) \ _BOOST_mingw_test(10, 1) \ _BOOST_gcc_test(10, 1) \ + _BOOST_mingw_test(9, 5) \ + _BOOST_gcc_test(9, 5) \ + _BOOST_mingw_test(9, 4) \ + _BOOST_gcc_test(9, 4) \ _BOOST_mingw_test(9, 3) \ _BOOST_gcc_test(9, 3) \ _BOOST_mingw_test(9, 2) \ @@ -1639,6 +1674,8 @@ if test x$boost_cv_inc_path != xno; then _BOOST_gcc_test(9, 1) \ _BOOST_mingw_test(9, 0) \ _BOOST_gcc_test(9, 0) \ + _BOOST_mingw_test(8, 5) \ + _BOOST_gcc_test(8, 5) \ _BOOST_mingw_test(8, 4) \ _BOOST_gcc_test(8, 4) \ _BOOST_mingw_test(8, 3) \ diff --git a/trackalert/Makefile.am b/trackalert/Makefile.am index 3639ee45..ad1fb238 100644 --- a/trackalert/Makefile.am +++ b/trackalert/Makefile.am @@ -18,7 +18,11 @@ AM_CPPFLAGS = $(LUA_CFLAGS) \ AM_LDFLAGS = \ $(PROGRAM_LDFLAGS) \ $(THREADFLAGS) \ - $(SANITIZER_FLAGS) + $(SANITIZER_FLAGS) \ + $(BOOST_DATE_TIME_LDFLAGS) \ + $(BOOST_FILESYSTEM_LDFLAGS) \ + $(BOOST_REGEX_LDFLAGS) \ + $(BOOST_SYSTEM_LDFLAGS) EXTRA_DIST= trackalert.conf README.md trackalert.service.in diff --git a/trackalert/trackalert.cc b/trackalert/trackalert.cc index 3e8cee0c..3ea8d834 100644 --- a/trackalert/trackalert.cc +++ b/trackalert/trackalert.cc @@ -157,12 +157,13 @@ try uint16_t len; if(!getMsgLen(fd, &len)) break; - char msg[len]; - readn2(fd, msg, len); + string msg; + msg.resize(len); + readn2(fd, msg.data(), len); - string line(msg, len); + string line; try { - line = sodDecryptSym(line, g_key, readingNonce); + line = sodDecryptSym(msg, g_key, readingNonce); } catch (std::runtime_error& e) { errlog("Could not decrypt client command: %s", e.what()); @@ -277,9 +278,9 @@ void doClient(ComboAddress server, const std::string& command) writen2(fd, msg); uint16_t len; getMsgLen(fd, &len); - char resp[len]; - readn2(fd, resp, len); - msg.assign(resp, len); + msg.clear(); + msg.resize(len); + readn2(fd, msg.data(), len); msg=sodDecryptSym(msg, g_key, readingNonce); cout< msgv; + + string msg; + msg.resize(len); + readn2(fd, msg.data(), len); + + string line; try { - line = sodDecryptSym(line, key, readingNonce); + line = sodDecryptSym(msg, key, readingNonce); } catch (std::runtime_error& e) { errlog("Could not decrypt client command: %s", e.what()); @@ -299,9 +302,9 @@ void doClient(ComboAddress server, const std::string& command) writen2(fd, msg); uint16_t len{0}; getMsgLen(fd, &len); - char resp[len]; - readn2(fd, resp, len); - msg.assign(resp, len); + msg.clear(); + msg.resize(len); + readn2(fd, msg.data(), len); msg=sodDecryptSym(msg, key, readingNonce); cout<