diff --git a/alertik.c b/alertik.c index 5247194..4e363a8 100644 --- a/alertik.c +++ b/alertik.c @@ -49,13 +49,11 @@ int main(void) pthread_t handler; int fd; -/* TODO: remove setup_notifiers().. - * think about env vars for the static events too, like enable/disable - */ - log_init(); - setup_notifiers(); - init_environment_events(); + + if (!init_static_events() && !init_environment_events()) + panic("No event was configured, please configure at least one\n" + "before proceeding!\n"); log_msg( "Alertik (" GIT_HASH ") (built at " __DATE__ " " __TIME__ ")\n"); diff --git a/env_events.c b/env_events.c index 616bffc..cb13658 100644 --- a/env_events.c +++ b/env_events.c @@ -147,8 +147,13 @@ int process_environment_event(struct log_event *ev) return handled; } - -/**/ +/** + * @brief Initialize environment variables events. + * + * @return Returns 0 if there is no environment event, + * 1 if there is at least one _and_ is successfully + * configured. +*/ int init_environment_events(void) { char *tmp; @@ -163,7 +168,7 @@ int init_environment_events(void) panic("Environment ENV_EVENTS exceeds the maximum supported (%d/%d)\n", num_env_events, MAX_ENV_EVENTS); - log_msg("%d environment events found, registering...\n"); + log_msg("%d environment event(s) found, registering...\n"); for (int i = 0; i < num_env_events; i++) { /* EVENTn_MATCH_TYPE. */ env_events[i].ev_match_type = get_event_idx(i, "MATCH_TYPE", @@ -193,5 +198,5 @@ int init_environment_events(void) /* Try to setup notifier if not yet. */ notifiers[env_events[i].ev_notifier_idx].setup(); } - return (0); + return 1; } diff --git a/events.c b/events.c index baf4125..9a0f3ba 100644 --- a/events.c +++ b/events.c @@ -3,12 +3,17 @@ * This is free and unencumbered software released into the public domain. */ +#include +#include #include +#include #include #include "events.h" #include "alertik.h" +#include "notifiers.h" +#include "log.h" -void handle_wifi_login_attempts(struct log_event *ev); +static void handle_wifi_login_attempts(struct log_event *, int); /* Handlers. */ struct ev_handler handlers[NUM_EVENTS] = { @@ -16,11 +21,36 @@ struct ev_handler handlers[NUM_EVENTS] = { { .str = "unicast key exchange timeout", .hnd = handle_wifi_login_attempts, - .evnt_type = EVNT_SUBSTR + .evnt_type = EVNT_SUBSTR, + .enabled = 0, + .evnt_notifier_idx = NOTIFY_IDX_TELE }, /* Add new handlers here. */ }; +/**/ +static char *get_event_str(long ev_num, char *str) +{ + char *env; + char ev[64] = {0}; + snprintf(ev, sizeof ev - 1, "STATIC_EVENT%ld_%s", ev_num, str); + if (!(env = getenv(ev))) + panic("Unable to find event for %s\n", ev); + return env; +} + +/**/ +static int +get_event_idx(long ev_num, char *str, const char *const *str_list, int size) +{ + char *env = get_event_str(ev_num, str); + for (int i = 0; i < size; i++) { + if (!strcmp(env, str_list[i])) + return i; + } + panic("String parameter (%s) invalid for %s\n", env, str); +} + /** * @brief Given an event, checks if it belongs to one of the * registered events and then, handle it. @@ -36,13 +66,77 @@ int process_static_event(struct log_event *ev) for (i = 0, handled = 0; i < NUM_EVENTS; i++) { if (strstr(ev->msg, handlers[i].str)) { - handlers[i].hnd(ev); + handlers[i].hnd(ev, i); handled += 1; } } return handled; } +/** + * @brief Initialize static events. + * + * @return Returns 0 if there is no static event, and 1 if + * there is at least one _and_ is successfully configured. +*/ +int init_static_events(void) +{ + char *ptr, *end; + long ev; + + /* Check for: STATIC_EVENTS_ENABLED=0,3,5,2... */ + ptr = getenv("STATIC_EVENTS_ENABLED"); + if (!ptr || ptr[0] == '\0') { + log_msg("Static events not detected, disabling...\n"); + return (0); + } + + end = ptr; + errno = 0; + + do + { + ev = strtol(end, &end, 10); + if (errno != 0 || ((ptr == end) && ev == 0)) + panic("Unable to parse STATIC_EVENTS_ENABLED, aborting...\n"); + + /* Skip whitespaces. */ + while (*end != '\0' && isspace(*end)) + end++; + + /* Check if ev number is sane. */ + if (ev < 0 || ev >= NUM_EVENTS) + panic("Event (%ld) is not valid!, should be between 0-%d\n", + ev, NUM_EVENTS - 1); + + /* Try to retrieve & initialize notifier for the event. */ + handlers[ev].evnt_notifier_idx = + get_event_idx(ev, "NOTIFIER", notifiers_str, NUM_NOTIFIERS); + handlers[ev].enabled = 1; + + if (*end != ',' && *end != '\0') + panic("Wrong event number in STATIC_EVENTS_ENABLED, aborting...\n"); + + } while (*end++ != '\0'); + + + log_msg("Static events summary:\n"); + for (int i = 0; i < NUM_EVENTS; i++) { + if (!handlers[i].enabled) + continue; + + printf( + "STATIC_EVENT%d : enabled\n" + "STATIC_EVENT%d_NOTIFIER: %s\n\n", + i, i, notifiers_str[handlers[i].evnt_notifier_idx] + ); + + /* Try to setup notifier if not yet. */ + notifiers[handlers[i].evnt_notifier_idx].setup(); + } + return 1; +} + ///////////////////////////// FAILED LOGIN ATTEMPTS /////////////////////////// static int @@ -79,12 +173,13 @@ parse_login_attempt_msg(const char *msg, char *wifi_iface, char *mac_addr) return (0); } -void handle_wifi_login_attempts(struct log_event *ev) +static void handle_wifi_login_attempts(struct log_event *ev, int idx_env) { char time_str[32] = {0}; char mac_addr[32] = {0}; char wifi_iface[32] = {0}; char notification_message[2048] = {0}; + int notif_idx; log_msg("> Login attempt detected!\n"); @@ -104,7 +199,8 @@ void handle_wifi_login_attempts(struct log_event *ev) log_msg("> Retrieved info, MAC: (%s), Interface: (%s)\n", mac_addr, wifi_iface); - if (send_telegram_notification(notification_message) < 0) { + notif_idx = handlers[idx_env].evnt_notifier_idx; + if (notifiers[notif_idx].send_notification(notification_message) < 0) { log_msg("unable to send the notification!\n"); return; } diff --git a/events.h b/events.h index edfcf10..7488f74 100644 --- a/events.h +++ b/events.h @@ -21,12 +21,15 @@ }; struct ev_handler { - const char *str; - void(*hnd)(struct log_event *); - int evnt_type; + const char *str; /* Substr or regex to match. */ + void(*hnd)(struct log_event *, int); /* Event handler. */ + int evnt_type; /* Whether substr or regex. */ + int evnt_notifier_idx; /* Telegram, Discord... */ + int enabled; /* Whether if handler enabled or not. */ }; extern struct ev_handler handlers[NUM_EVENTS]; extern int process_static_event(struct log_event *ev); + extern int init_static_events(void); #endif /* EVENTS_H */ diff --git a/notifiers.c b/notifiers.c index ac3d0d7..a2027bd 100644 --- a/notifiers.c +++ b/notifiers.c @@ -132,10 +132,3 @@ struct notifier notifiers[] = { .send_notification = send_telegram_notification } }; - -/* Global setup. */ -void setup_notifiers(void) -{ - for (int i = 0; i < NUM_NOTIFIERS; i++) - notifiers[i].setup(); -} diff --git a/notifiers.h b/notifiers.h index 7a71b4d..1928860 100644 --- a/notifiers.h +++ b/notifiers.h @@ -11,6 +11,11 @@ // #define VALIDATE_CERTS // #define DISABLE_NOTIFICATIONS + /* + * Notifier indexes. + */ + #define NOTIFY_IDX_TELE 0 + #define CURL_USER_AGENT "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " \ "(KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" @@ -34,7 +39,6 @@ }; extern struct notifier notifiers[NUM_NOTIFIERS]; - extern void setup_notifiers(void); extern int is_within_notify_threshold(void); extern void update_notify_last_sent(void);