Skip to content

Commit

Permalink
Merge pull request #439 from neilcook/packaging
Browse files Browse the repository at this point in the history
Fix OL-9 packaging and avoid use of non C++ standard VLAs
  • Loading branch information
neilcook authored Dec 2, 2024
2 parents c1a356f + 6b3213f commit f7954f0
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 60 deletions.
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

0 comments on commit f7954f0

Please sign in to comment.