Add unit tests for forced encryption check function
Some checks failed
CI / Check spelling (pull_request) Successful in 20s
CI / Check coding style (pull_request) Successful in 31s
CI / Linux (debian) (pull_request) Failing after 3m30s
CI / Linux (ubuntu) (pull_request) Successful in 12m13s
CI / Linux (arch) (pull_request) Successful in 17m57s
Some checks failed
CI / Check spelling (pull_request) Successful in 20s
CI / Check coding style (pull_request) Successful in 31s
CI / Linux (debian) (pull_request) Failing after 3m30s
CI / Linux (ubuntu) (pull_request) Successful in 12m13s
CI / Linux (arch) (pull_request) Successful in 17m57s
This commit is contained in:
@@ -166,6 +166,7 @@ unittest_sources = \
|
||||
tests/unittests/test_cmd_disconnect.c tests/unittests/test_cmd_disconnect.h \
|
||||
tests/unittests/test_callbacks.c tests/unittests/test_callbacks.h \
|
||||
tests/unittests/test_plugins_disco.c tests/unittests/test_plugins_disco.h \
|
||||
tests/unittests/test_forced_encryption.c tests/unittests/test_forced_encryption.h \
|
||||
tests/unittests/unittests.c
|
||||
|
||||
functionaltest_sources = \
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "log.h"
|
||||
#include "chatlog.h"
|
||||
#include "database.h"
|
||||
#include "client_events.h"
|
||||
#include "config/preferences.h"
|
||||
#include "event/common.h"
|
||||
#include "plugins/plugins.h"
|
||||
@@ -130,38 +131,6 @@ cl_ev_presence_send(const resource_presence_t presence_type, const int idle_secs
|
||||
presence_send(presence_type, idle_secs, signed_status);
|
||||
}
|
||||
|
||||
// Checks if an unencrypted message can be sent based on encryption preferences.
|
||||
// Returns TRUE if allowed, FALSE if blocked.
|
||||
static gboolean
|
||||
_allow_unencrypted_message(ProfChatWin* chatwin, const char* const msg)
|
||||
{
|
||||
if (!prefs_get_boolean(PREF_FORCE_ENCRYPTION)) {
|
||||
return TRUE; // Encryption not enforced
|
||||
}
|
||||
|
||||
auto_gchar gchar* force_enc_mode = prefs_get_string(PREF_FORCE_ENCRYPTION_MODE);
|
||||
|
||||
if (g_strcmp0(force_enc_mode, "block") == 0) {
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or /force-encryption off.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(force_enc_mode, "resend-to-confirm") == 0) {
|
||||
// We do not use chatwin->last_message because it should be set only if it's sent.
|
||||
guint msg_hash = g_str_hash(msg);
|
||||
if (msg_hash != chatwin->last_attempted_msg_hash) {
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or press Enter again to send without encryption. Use /force-encryption off to disable this protection.");
|
||||
chatwin->last_attempted_msg_hash = msg_hash;
|
||||
inp_set_line(msg); // reset message to prevent the need to retype it
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: invalid encryption mode (%s). Use '/force-encryption policy resend-to-confirm'.", force_enc_mode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
cl_ev_send_msg_correct(ProfChatWin* chatwin, const char* const msg, const char* const oob_url, gboolean correct_last_msg)
|
||||
{
|
||||
@@ -210,7 +179,7 @@ cl_ev_send_msg_correct(ProfChatWin* chatwin, const char* const msg, const char*
|
||||
#ifdef HAVE_LIBOTR
|
||||
handled = otr_on_message_send(chatwin, message, request_receipt, replace_id);
|
||||
#endif
|
||||
if (!handled && _allow_unencrypted_message(chatwin, message)) {
|
||||
if (!handled && allow_unencrypted_message(chatwin, message)) {
|
||||
auto_char char* id = message_send_chat(chatwin->barejid, message, oob_url, request_receipt, replace_id);
|
||||
chat_log_msg_out(chatwin->barejid, message, NULL);
|
||||
log_database_add_outgoing_chat(id, chatwin->barejid, message, replace_id, PROF_MSG_ENC_NONE);
|
||||
@@ -284,3 +253,34 @@ cl_ev_send_priv_msg(ProfPrivateWin* privwin, const char* const msg, const char*
|
||||
plugins_post_priv_message_send(privwin->fulljid, message);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
allow_unencrypted_message(ProfChatWin* chatwin, const char* const msg)
|
||||
{
|
||||
if (!prefs_get_boolean(PREF_FORCE_ENCRYPTION)) {
|
||||
return TRUE; // Encryption not enforced
|
||||
}
|
||||
|
||||
auto_gchar gchar* force_enc_mode = prefs_get_string(PREF_FORCE_ENCRYPTION_MODE);
|
||||
|
||||
if (g_strcmp0(force_enc_mode, "block") == 0) {
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or /force-encryption off.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(force_enc_mode, "resend-to-confirm") == 0) {
|
||||
// We do not use chatwin->last_message because it should be set only if it's sent.
|
||||
guint msg_hash = g_str_hash(msg);
|
||||
if (msg_hash == chatwin->last_attempted_msg_hash) {
|
||||
chatwin->last_attempted_msg_hash = 0; // reset hash
|
||||
return TRUE;
|
||||
}
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or press Enter again to send without encryption. Use /force-encryption off to disable this protection.");
|
||||
chatwin->last_attempted_msg_hash = msg_hash;
|
||||
inp_set_line(msg); // reset message to prevent the need to retype it
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
win_println((ProfWin*)chatwin, THEME_ERROR, "-", "Message not sent: invalid encryption mode (%s). Use '/force-encryption policy resend-to-confirm'.", force_enc_mode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -52,4 +52,8 @@ void cl_ev_send_muc_msg_corrected(ProfMucWin* mucwin, const char* const msg, con
|
||||
void cl_ev_send_muc_msg(ProfMucWin* mucwin, const char* const msg, const char* const oob_url);
|
||||
void cl_ev_send_priv_msg(ProfPrivateWin* privwin, const char* const msg, const char* const oob_url);
|
||||
|
||||
// Checks if an unencrypted message can be sent based on encryption preferences.
|
||||
// Returns TRUE if allowed, FALSE if blocked.
|
||||
gboolean allow_unencrypted_message(ProfChatWin* chatwin, const char* const msg);
|
||||
|
||||
#endif
|
||||
|
||||
133
tests/unittests/test_forced_encryption.c
Normal file
133
tests/unittests/test_forced_encryption.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
#include <glib.h>
|
||||
#include "event/client_events.h"
|
||||
#include "command/cmd_funcs.h"
|
||||
#include "config/preferences.h"
|
||||
#include "ui/stub_ui.h"
|
||||
|
||||
#define CMD_FORCE_ENCRYPTION "/force-encryption"
|
||||
|
||||
// Test: /force-encryption with no arguments shows error.
|
||||
void
|
||||
test_cmd_force_encryption_no_args_bad_cmd(void** state)
|
||||
{
|
||||
char* args[] = { NULL };
|
||||
expect_string(cons_bad_cmd_usage, cmd, CMD_FORCE_ENCRYPTION);
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
}
|
||||
|
||||
// Test: /force-encryption on enables encryption.
|
||||
void
|
||||
test_cmd_force_encryption_toggles_on(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, FALSE);
|
||||
char* args[] = { "on", NULL };
|
||||
expect_cons_show("Forces encryption enabled.");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_true(prefs_get_boolean(PREF_FORCE_ENCRYPTION));
|
||||
}
|
||||
|
||||
// Test: /force-encryption off disables encryption.
|
||||
void
|
||||
test_cmd_force_encryption_toggles_off(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, TRUE);
|
||||
char* args[] = { "off", NULL };
|
||||
expect_cons_show("Forces encryption disabled.");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_false(prefs_get_boolean(PREF_FORCE_ENCRYPTION));
|
||||
}
|
||||
|
||||
// Test: /force-encryption off when already off.
|
||||
void
|
||||
test_cmd_force_encryption_toggles_off_already(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, FALSE);
|
||||
char* args[] = { "off", NULL };
|
||||
expect_cons_show("Forces encryption is already disabled.");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_false(prefs_get_boolean(PREF_FORCE_ENCRYPTION));
|
||||
}
|
||||
|
||||
// Test: /force-encryption on when already on.
|
||||
void
|
||||
test_cmd_force_encryption_toggles_on_already(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, TRUE);
|
||||
char* args[] = { "on", NULL };
|
||||
expect_cons_show("Forces encryption is already enabled.");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_true(prefs_get_boolean(PREF_FORCE_ENCRYPTION));
|
||||
}
|
||||
|
||||
// Test: /force-encryption policy block sets block mode.
|
||||
void
|
||||
test_cmd_force_encryption_sets_policy_block(void** state)
|
||||
{
|
||||
char* args[] = { "policy", "block", NULL };
|
||||
expect_cons_show("Force encryption policy has been set to \"block\".");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_string_equal(prefs_get_string(PREF_FORCE_ENCRYPTION_MODE), "block");
|
||||
}
|
||||
|
||||
// Test: /force-encryption policy resend-to-confirm sets resend mode.
|
||||
void
|
||||
test_cmd_force_encryption_sets_policy_resend(void** state)
|
||||
{
|
||||
char* args[] = { "policy", "resend-to-confirm", NULL };
|
||||
expect_cons_show("Force encryption policy has been set to \"resend-to-confirm\".");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
assert_string_equal(prefs_get_string(PREF_FORCE_ENCRYPTION_MODE), "resend-to-confirm");
|
||||
}
|
||||
|
||||
// Test: Unencrypted message blocked when policy is block.
|
||||
void
|
||||
test_allow_unencrypted_message_blocks(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, TRUE);
|
||||
prefs_set_string(PREF_FORCE_ENCRYPTION_MODE, "block");
|
||||
ProfChatWin win = {};
|
||||
char* msg = "test message";
|
||||
expect_win_println("Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or /force-encryption off.");
|
||||
assert_false(allow_unencrypted_message(&win, msg));
|
||||
}
|
||||
|
||||
// Test: Unencrypted message prompts confirmation, then allows on second attempt.
|
||||
void
|
||||
test_allow_unencrypted_message_confirms_on_second_attempt(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, TRUE);
|
||||
prefs_set_string(PREF_FORCE_ENCRYPTION_MODE, "resend-to-confirm");
|
||||
ProfChatWin win = { .last_attempted_msg_hash = 0 };
|
||||
char* msg = "test message";
|
||||
expect_win_println("Message not sent: encryption required. Enable (omemo/pgp/otr) encryption or press Enter again to send without encryption. Use /force-encryption off to disable this protection.");
|
||||
assert_false(allow_unencrypted_message(&win, msg));
|
||||
assert_int_not_equal(win.last_attempted_msg_hash, 0);
|
||||
assert_true(allow_unencrypted_message(&win, msg));
|
||||
assert_int_equal(win.last_attempted_msg_hash, 0); // ensure that value resets since we don't want to approve the same message twice
|
||||
}
|
||||
|
||||
// Test: Invalid policy argument fails gracefully.
|
||||
void
|
||||
test_cmd_force_encryption_invalid_policy(void** state)
|
||||
{
|
||||
char* args[] = { "policy", "invalid", NULL };
|
||||
expect_cons_show_error("Invalid policy: \"invalid\". See '/help force-encryption' for details.");
|
||||
assert_true(cmd_force_encryption(NULL, CMD_FORCE_ENCRYPTION, args));
|
||||
}
|
||||
|
||||
// Test: Invalid encryption mode blocks message.
|
||||
void
|
||||
test_allow_unencrypted_message_invalid_mode(void** state)
|
||||
{
|
||||
prefs_set_boolean(PREF_FORCE_ENCRYPTION, TRUE);
|
||||
prefs_set_string(PREF_FORCE_ENCRYPTION_MODE, "invalid");
|
||||
ProfChatWin win = { .last_attempted_msg_hash = 0 };
|
||||
char* msg = "test message";
|
||||
expect_win_println("Message not sent: invalid encryption mode (invalid). Use '/force-encryption policy resend-to-confirm'.");
|
||||
assert_false(allow_unencrypted_message(&win, msg));
|
||||
assert_int_equal(win.last_attempted_msg_hash, 0);
|
||||
}
|
||||
16
tests/unittests/test_forced_encryption.h
Normal file
16
tests/unittests/test_forced_encryption.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef TEST_FORCED_ENCRYPTION_H
|
||||
#define TEST_FORCED_ENCRYPTION_H
|
||||
|
||||
void test_cmd_force_encryption_no_args_bad_cmd(void** state);
|
||||
void test_cmd_force_encryption_toggles_on(void** state);
|
||||
void test_cmd_force_encryption_toggles_off(void** state);
|
||||
void test_cmd_force_encryption_toggles_off_already(void** state);
|
||||
void test_cmd_force_encryption_toggles_on_already(void** state);
|
||||
void test_cmd_force_encryption_sets_policy_block(void** state);
|
||||
void test_cmd_force_encryption_sets_policy_resend(void** state);
|
||||
void test_allow_unencrypted_message_blocks(void** state);
|
||||
void test_allow_unencrypted_message_confirms_on_second_attempt(void** state);
|
||||
void test_cmd_force_encryption_invalid_policy(void** state);
|
||||
void test_allow_unencrypted_message_invalid_mode(void** state);
|
||||
|
||||
#endif // TEST_FORCED_ENCRYPTION_H
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "test_cmd_presence.h"
|
||||
#include "test_cmd_otr.h"
|
||||
#include "test_cmd_pgp.h"
|
||||
#include "test_forced_encryption.h"
|
||||
#include "test_jid.h"
|
||||
#include "test_parser.h"
|
||||
#include "test_roster_list.h"
|
||||
@@ -644,6 +645,19 @@ main(int argc, char* argv[])
|
||||
cmocka_unit_test(does_not_add_duplicate_feature),
|
||||
cmocka_unit_test(removes_plugin_features),
|
||||
cmocka_unit_test(does_not_remove_feature_when_more_than_one_reference),
|
||||
|
||||
// Forced encryption
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_no_args_bad_cmd, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_toggles_on, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_toggles_off, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_toggles_off_already, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_toggles_on_already, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_sets_policy_block, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_sets_policy_resend, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_allow_unencrypted_message_blocks, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_allow_unencrypted_message_confirms_on_second_attempt, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_cmd_force_encryption_invalid_policy, load_preferences, close_preferences),
|
||||
cmocka_unit_test_setup_teardown(test_allow_unencrypted_message_invalid_mode, load_preferences, close_preferences),
|
||||
};
|
||||
return cmocka_run_group_tests(all_tests, NULL, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user