Merge pull request #1827 from H3rnand3zzz/feature/sessions-alarm

New Feature: Session Alarm
This commit is contained in:
Michael Vetter
2023-04-18 14:43:01 +02:00
committed by GitHub
18 changed files with 180 additions and 24 deletions

View File

@@ -485,6 +485,7 @@ cmd_ac_init(void)
autocomplete_add(account_set_ac, "tls");
autocomplete_add(account_set_ac, "auth");
autocomplete_add(account_set_ac, "theme");
autocomplete_add(account_set_ac, "session_alarm");
account_clear_ac = autocomplete_new();
autocomplete_add(account_clear_ac, "password");
@@ -498,6 +499,7 @@ cmd_ac_init(void)
autocomplete_add(account_clear_ac, "theme");
autocomplete_add(account_clear_ac, "muc");
autocomplete_add(account_clear_ac, "resource");
autocomplete_add(account_clear_ac, "session_alarm");
account_default_ac = autocomplete_new();
autocomplete_add(account_default_ac, "set");

View File

@@ -2070,6 +2070,7 @@ static const struct cmd_t command_defs[] = {
"/account set <account> tls force|allow|trust|legacy|disable",
"/account set <account> auth default|legacy",
"/account set <account> theme <theme>",
"/account set <account> session_alarm <max_sessions>",
"/account clear <account> password",
"/account clear <account> eval_password",
"/account clear <account> server",
@@ -2079,7 +2080,8 @@ static const struct cmd_t command_defs[] = {
"/account clear <account> startscript",
"/account clear <account> clientid",
"/account clear <account> muc",
"/account clear <account> resource")
"/account clear <account> resource",
"/account clear <account> session_alarm")
CMD_DESC(
"Commands for creating and managing accounts. "
"Calling with no arguments will display information for the current account.")
@@ -2116,6 +2118,7 @@ static const struct cmd_t command_defs[] = {
{ "set <account> auth default", "Use default authentication process." },
{ "set <account> auth legacy", "Allow legacy authentication." },
{ "set <account> theme <theme>", "Set the UI theme for the account." },
{ "set <account> session_alarm <max_sessions>", "Alarm about suspicious activity if sessions count exceeds max_sessions." },
{ "clear <account> server", "Remove the server setting for this account." },
{ "clear <account> port", "Remove the port setting for this account." },
{ "clear <account> password", "Remove the password setting for this account." },
@@ -2126,7 +2129,8 @@ static const struct cmd_t command_defs[] = {
{ "clear <account> clientid", "Reset client's name to default." },
{ "clear <account> theme", "Clear the theme setting for the account, the global theme will be used." },
{ "clear <account> resource", "Remove the resource setting for this account." },
{ "clear <account> muc", "Remove the default MUC service setting." })
{ "clear <account> muc", "Remove the default MUC service setting." },
{ "clear <account> session_alarm", "Disable the session alarm." })
CMD_EXAMPLES(
"/account add me",
"/account set me jid ulfhednar@valhalla.edda",

View File

@@ -904,6 +904,28 @@ _account_set_auth(char* account_name, char* policy)
return TRUE;
}
gboolean
_account_set_max_sessions(char* account_name, char* max_sessions_raw)
{
int max_sessions;
char* err_msg = NULL;
gboolean res = strtoi_range(max_sessions_raw, &max_sessions, 0, INT_MAX, &err_msg);
if (!res) {
cons_show(err_msg);
cons_show("");
free(err_msg);
return TRUE;
}
accounts_set_max_sessions(account_name, max_sessions);
if (max_sessions < 1) {
cons_show("Max sessions alarm for account %s has been disabled.", account_name);
} else {
cons_show("Max sessions alarm for account %s has been set to %d", account_name, max_sessions);
}
cons_show("");
return TRUE;
}
gboolean
_account_set_presence_priority(char* account_name, char* presence, char* priority)
{
@@ -997,6 +1019,8 @@ cmd_account_set(ProfWin* window, const char* const command, gchar** args)
return _account_set_tls(account_name, value);
if (strcmp(property, "auth") == 0)
return _account_set_auth(account_name, value);
if (strcmp(property, "session_alarm") == 0)
return _account_set_max_sessions(account_name, value);
if (valid_resource_presence_string(property)) {
return _account_set_presence_priority(account_name, property, value);
@@ -1057,6 +1081,9 @@ cmd_account_clear(ProfWin* window, const char* const command, gchar** args)
} else if (strcmp(property, "resource") == 0) {
accounts_clear_resource(account_name);
cons_show("Removed resource for account %s", account_name);
} else if (strcmp(property, "session_alarm") == 0) {
accounts_clear_max_sessions(account_name);
cons_show("Disabled session alarm for account %s", account_name);
} else {
cons_show("Invalid property: %s", property);
}

View File

@@ -57,7 +57,7 @@ account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_password, gboo
gchar* omemo_policy, GList* omemo_enabled, GList* omemo_disabled,
GList* ox_enabled, GList* pgp_enabled, gchar* pgp_keyid,
gchar* startscript, gchar* theme, gchar* tls_policy, gchar* auth_policy,
gchar* client)
gchar* client, int max_sessions)
{
ProfAccount* new_account = calloc(1, sizeof(ProfAccount));
@@ -140,6 +140,8 @@ account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_password, gboo
new_account->auth_policy = auth_policy;
new_account->max_sessions = max_sessions;
return new_account;
}

View File

@@ -72,6 +72,7 @@ typedef struct prof_account_t
gchar* tls_policy;
gchar* auth_policy;
gchar* client;
int max_sessions;
} ProfAccount;
ProfAccount* account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_password, gboolean enabled,
@@ -82,7 +83,7 @@ ProfAccount* account_new(gchar* name, gchar* jid, gchar* password, gchar* eval_p
gchar* omemo_policy, GList* omemo_enabled, GList* omemo_disabled,
GList* ox_enabled, GList* pgp_enabled, gchar* pgp_keyid,
gchar* startscript, gchar* theme, gchar* tls_policy, gchar* auth_policy,
gchar* client);
gchar* client, int max_sessions);
char* account_create_connect_jid(ProfAccount* account);
gboolean account_eval_password(ProfAccount* account);
void account_free(ProfAccount* account);

View File

@@ -347,13 +347,15 @@ accounts_get_account(const char* const name)
gchar* auth_policy = g_key_file_get_string(accounts, name, "auth.policy", NULL);
int max_sessions = g_key_file_get_integer(accounts, name, "max.sessions", 0);
ProfAccount* new_account = account_new(g_strdup(name), jid, password, eval_password, enabled,
server, port, resource, last_presence, login_presence,
priority_online, priority_chat, priority_away, priority_xa,
priority_dnd, muc_service, muc_nick, otr_policy, otr_manual,
otr_opportunistic, otr_always, omemo_policy, omemo_enabled,
omemo_disabled, ox_enabled, pgp_enabled, pgp_keyid,
startscript, theme, tls_policy, auth_policy, client);
startscript, theme, tls_policy, auth_policy, client, max_sessions);
return new_account;
}
@@ -568,6 +570,12 @@ accounts_set_theme(const char* const account_name, const char* const value)
_accounts_set_string_option(account_name, "theme", value);
}
void
accounts_set_max_sessions(const char* const account_name, const int value)
{
_accounts_set_int_option(account_name, "max.sessions", value);
}
void
accounts_clear_password(const char* const account_name)
{
@@ -634,6 +642,12 @@ accounts_clear_otr(const char* const account_name)
_accounts_clear_string_option(account_name, "otr.policy");
}
void
accounts_clear_max_sessions(const char* const account_name)
{
_accounts_clear_string_option(account_name, "max.sessions");
}
void
accounts_add_otr_policy(const char* const account_name, const char* const contact_jid, const char* const policy)
{
@@ -865,6 +879,24 @@ accounts_get_last_activity(const char* const account_name)
}
}
char*
accounts_get_resource(const char* const account_name)
{
if (!accounts_account_exists(account_name)) {
return NULL;
}
return g_key_file_get_string(accounts, account_name, "resource", NULL);
}
int
accounts_get_max_sessions(const char* const account_name)
{
if (!accounts_account_exists(account_name)) {
return 0;
}
return g_key_file_get_integer(accounts, account_name, "max.sessions", 0);
}
void
accounts_set_login_presence(const char* const account_name, const char* const value)
{

View File

@@ -61,6 +61,7 @@ void accounts_set_jid(const char* const account_name, const char* const value);
void accounts_set_server(const char* const account_name, const char* const value);
void accounts_set_port(const char* const account_name, const int value);
void accounts_set_resource(const char* const account_name, const char* const value);
char* accounts_get_resource(const char* const account_name);
void accounts_set_password(const char* const account_name, const char* const value);
void accounts_set_eval_password(const char* const account_name, const char* const value);
void accounts_set_muc_service(const char* const account_name, const char* const value);
@@ -89,6 +90,8 @@ void accounts_set_pgp_keyid(const char* const account_name, const char* const va
void accounts_set_script_start(const char* const account_name, const char* const value);
void accounts_set_client(const char* const account_name, const char* const value);
void accounts_set_theme(const char* const account_name, const char* const value);
void accounts_set_max_sessions(const char* const account_name, const int value);
int accounts_get_max_sessions(const char* const account_name);
void accounts_clear_password(const char* const account_name);
void accounts_clear_eval_password(const char* const account_name);
void accounts_clear_server(const char* const account_name);
@@ -100,6 +103,7 @@ void accounts_clear_client(const char* const account_name);
void accounts_clear_theme(const char* const account_name);
void accounts_clear_muc(const char* const account_name);
void accounts_clear_resource(const char* const account_name);
void accounts_clear_max_sessions(const char* const account_name);
void accounts_add_otr_policy(const char* const account_name, const char* const contact_jid, const char* const policy);
void accounts_add_omemo_state(const char* const account_name, const char* const contact_jid, gboolean enabled);
void accounts_add_ox_state(const char* const account_name, const char* const contact_jid, gboolean enabled);

View File

@@ -1067,6 +1067,9 @@ cons_show_account(ProfAccount* account)
if (account->client) {
cons_show("Client name : %s", account->client);
}
if (account->max_sessions > 0) {
cons_show("Max sessions alarm: %d", account->max_sessions);
}
if (account->theme) {
cons_show("Theme : %s", account->theme);
}
@@ -1123,11 +1126,12 @@ cons_show_account(ProfAccount* account)
if ((connection_get_status() == JABBER_CONNECTED) && (g_strcmp0(session_get_account_name(), account->name) == 0)) {
GList* resources = connection_get_available_resources();
int resources_count = connection_count_available_resources();
GList* ordered_resources = NULL;
GList* curr = resources;
if (curr) {
win_println(console, THEME_DEFAULT, "-", "Resources:");
win_println(console, THEME_DEFAULT, "-", "Resources (%u):", resources_count);
// sort in order of availability
while (curr) {

View File

@@ -776,6 +776,12 @@ connection_get_available_resources(void)
return g_hash_table_get_values(conn.available_resources);
}
int
connection_count_available_resources(void)
{
return g_hash_table_size(conn.available_resources);
}
void
connection_add_available_resource(Resource* resource)
{

View File

@@ -51,6 +51,8 @@
#include "event/server_events.h"
#include "plugins/plugins.h"
#include "ui/ui.h"
#include "ui/window.h"
#include "ui/window_list.h"
#include "xmpp/connection.h"
#include "xmpp/capabilities.h"
#include "xmpp/session.h"
@@ -656,6 +658,68 @@ _available_handler(xmpp_stanza_t* const stanza)
if (g_strcmp0(xmpp_presence->jid->barejid, my_jid->barejid) == 0) {
connection_add_available_resource(resource);
const char* account_name = session_get_account_name();
int max_sessions = accounts_get_max_sessions(account_name);
if (max_sessions > 0) {
const char* cur_resource = accounts_get_resource(account_name);
int res_count = connection_count_available_resources();
if (res_count > max_sessions && g_strcmp0(cur_resource, resource->name)) {
ProfWin* console = wins_get_console();
ProfWin* current_window = wins_get_current();
auto_gchar gchar* message = g_strdup_printf("Max sessions alarm! (%d/%d devices in use)", res_count, max_sessions);
win_println(console, THEME_RED, "|", "%s", message);
if (console != current_window) {
win_println(current_window, THEME_RED, "|", "%s - check the console for more details!", message);
}
notify(message, 10000, "Security alert");
const char* resource_presence = string_from_resource_presence(resource->presence);
win_print(console, THEME_DEFAULT, "|", "New device info: \n %s (%d), %s", resource->name, resource->priority, resource_presence);
if (resource->status) {
win_append(console, THEME_DEFAULT, ", \"%s\"", resource->status);
}
win_appendln(console, THEME_DEFAULT, "");
auto_jid Jid* jidp = jid_create_from_bare_and_resource(my_jid->barejid, resource->name);
EntityCapabilities* caps = caps_lookup(jidp->fulljid);
if (caps) {
if (caps->identity) {
DiscoIdentity* identity = caps->identity;
win_print(console, THEME_DEFAULT, "|", " %s %s %s", identity->name, identity->type, identity->category);
win_newline(console);
}
if (caps->software_version) {
SoftwareVersion* software_version = caps->software_version;
if (software_version->software) {
win_print(console, THEME_DEFAULT, "|", " Software: %s", software_version->software);
}
if (software_version->software_version) {
win_append(console, THEME_DEFAULT, ", %s", software_version->software_version);
}
if (software_version->software || software_version->software_version) {
win_newline(console);
}
if (software_version->os) {
win_print(console, THEME_DEFAULT, "|", " OS: %s", software_version->os);
}
if (software_version->os_version) {
win_append(console, THEME_DEFAULT, ", %s", software_version->os_version);
}
if (software_version->os || software_version->os_version) {
win_newline(console);
}
}
caps_destroy(caps);
}
win_println(console, THEME_RED_BOLD, "|", "If it wasn't you, change your password. Use: /changepassword");
win_println(console, THEME_GREEN, "|", "If it was you, update the `session_alarm` limit that determines when to trigger this alarm, use: /account set %s session_alarm %d", account_name, res_count);
cons_alert(NULL);
}
}
} else {
char* pgpsig = NULL;
xmpp_stanza_t* x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_SIGNED);

View File

@@ -199,6 +199,7 @@ TLSCertificate* connection_get_tls_peer_cert(void);
gboolean connection_is_secured(void);
gboolean connection_send_stanza(const char* const stanza);
GList* connection_get_available_resources(void);
int connection_count_available_resources(void);
gboolean connection_supports(const char* const feature);
char* connection_jid_for_feature(const char* const feature);