Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix OL-9 packaging and avoid use of non C++ standard VLAs #439

Merged
merged 9 commits into from
Dec 2, 2024
1 change: 1 addition & 0 deletions builder-support/specs/wforce.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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} \
Expand Down
3 changes: 2 additions & 1 deletion common/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
65 changes: 38 additions & 27 deletions common/sodcrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(nullptr, EVP_CIPHER_CTX_free);

Expand All @@ -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<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(nullptr, EVP_CIPHER_CTX_free);

Expand All @@ -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, decltype(&EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free)))
Expand All @@ -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();
Expand Down
10 changes: 5 additions & 5 deletions common/sodcrypto.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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();
25 changes: 25 additions & 0 deletions common/test-crypto.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <boost/test/unit_test.hpp>
#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();
43 changes: 40 additions & 3 deletions m4/boost.m4
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

m4_define([_BOOST_SERIAL], [m4_translit([
# serial 34
# serial 38
], [#
], [])])

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" \
Expand All @@ -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) \
Expand All @@ -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) \
Expand Down
6 changes: 5 additions & 1 deletion trackalert/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
23 changes: 12 additions & 11 deletions trackalert/trackalert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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<<msg<<endl;
close(fd);
Expand Down Expand Up @@ -319,10 +320,10 @@ 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=sodDecryptSym(msg, g_key, readingNonce);
string resp;
resp.resize(len);
readn2(fd, resp.data(), len);
msg=sodDecryptSym(resp, g_key, readingNonce);
cout<<msg<<endl;
}
}
Expand Down
6 changes: 5 additions & 1 deletion wforce/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ AM_CPPFLAGS = \
AM_LDFLAGS = \
$(PROGRAM_LDFLAGS) \
$(THREADFLAGS) \
$(SANITIZER_FLAGS)
$(SANITIZER_FLAGS) \
$(BOOST_DATE_TIME_LDFLAGS) \
$(BOOST_FILESYSTEM_LDFLAGS) \
$(BOOST_REGEX_LDFLAGS) \
$(BOOST_SYSTEM_LDFLAGS)

UAP_REGEX_FILE=regexes.yaml

Expand Down
2 changes: 2 additions & 0 deletions wforce/replication.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ bool ReplicationOperation::unserialize(const std::string& str)
}
else
retval = false;
} else {
errlog("ReplicationOperation:unserialize error - cannot parse received replication msg");
}
forwarded = msg.forwarded();
return retval;
Expand Down
Loading
Loading