diff options
Diffstat (limited to 'src/plugins/ifw')
-rw-r--r-- | src/plugins/ifw/black_list.c | 76 | ||||
-rw-r--r-- | src/plugins/ifw/black_list.h | 20 | ||||
-rw-r--r-- | src/plugins/ifw/ifw.h | 48 | ||||
-rw-r--r-- | src/plugins/ifw/ifw_dbus.c | 456 | ||||
-rw-r--r-- | src/plugins/ifw/ifw_dbus.h | 43 | ||||
-rw-r--r-- | src/plugins/ifw/ipset.c | 89 | ||||
-rw-r--r-- | src/plugins/ifw/ipset.h | 22 | ||||
-rw-r--r-- | src/plugins/ifw/libnl_ifw.c | 62 | ||||
-rw-r--r-- | src/plugins/ifw/libnl_ifw.h | 35 | ||||
-rw-r--r-- | src/plugins/ifw/list.h | 155 | ||||
-rw-r--r-- | src/plugins/ifw/plugin.c | 224 | ||||
-rw-r--r-- | src/plugins/ifw/report_list.c | 81 | ||||
-rw-r--r-- | src/plugins/ifw/report_list.h | 24 | ||||
-rw-r--r-- | src/plugins/ifw/white_list.c | 119 | ||||
-rw-r--r-- | src/plugins/ifw/white_list.h | 23 |
15 files changed, 1477 insertions, 0 deletions
diff --git a/src/plugins/ifw/black_list.c b/src/plugins/ifw/black_list.c new file mode 100644 index 0000000..1e7dbbb --- /dev/null +++ b/src/plugins/ifw/black_list.c @@ -0,0 +1,76 @@ +#include "black_list.h" +#include "ipset.h" + +#include <stdio.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +void black_list_init(black_list_t *list) { + INIT_LIST_HEAD(list); +} + +void black_list_add(black_list_t *list, msg_usr_t *attack) { + black_list_cell_t *cell; + + cell = malloc(sizeof(black_list_cell_t)); + if (!cell) { + fprintf(stderr, "unable to alloc enough memory for black list cell, skipping\n"); + return; + } + cell->info = *attack; + INIT_LIST_HEAD(&cell->list); + list_add_tail(&cell->list, list); + + ipset_blacklist_add(cell->info.s_addr); +} + +black_list_cell_t *black_list_find(black_list_t *list, u_int32_t addr) { + struct list_head *entry; + + __list_for_each(entry, list) { + black_list_cell_t *cell; + cell = list_entry(entry, black_list_cell_t, list); + if (cell->info.s_addr == addr) { + return cell; + } + } + + return NULL; +} + +void black_list_remove(black_list_t *list, u_int32_t addr) { + black_list_cell_t *cell, *n, *prev; + + ipset_blacklist_remove(addr); + + prev = NULL; + list_for_each_entry_safe(cell, n, list, list) { + if (prev) + free(prev); + if (cell->info.s_addr == addr) { + list_del(&cell->list); + prev = cell; + } else { + prev = NULL; + } + } + if (prev) + free(prev); +} + + +void black_list_print(black_list_t *list) { + struct list_head *entry; + + printf("* black list {\n"); + __list_for_each(entry, list) { + black_list_cell_t *cell; + struct in_addr addr; + cell = list_entry(entry, black_list_cell_t, list); + addr.s_addr = cell->info.s_addr; + printf("%s,\n", inet_ntoa(addr)); + } + printf("} black list *\n"); +} diff --git a/src/plugins/ifw/black_list.h b/src/plugins/ifw/black_list.h new file mode 100644 index 0000000..4cfe74b --- /dev/null +++ b/src/plugins/ifw/black_list.h @@ -0,0 +1,20 @@ +#ifndef BLACK_LIST_H +#define BLACK_LIST_H + +#include "list.h" +typedef struct list_head black_list_t; + +#include "ifw.h" + +typedef struct { + struct list_head list; + msg_usr_t info; +} black_list_cell_t; + +void black_list_init(black_list_t *list); +void black_list_add(black_list_t *list, msg_usr_t *attack); +black_list_cell_t *black_list_find(black_list_t *list, u_int32_t addr); +void black_list_remove(black_list_t *list, u_int32_t addr); +void black_list_print(black_list_t *list); + +#endif /* BLACK_LIST_H */ diff --git a/src/plugins/ifw/ifw.h b/src/plugins/ifw/ifw.h new file mode 100644 index 0000000..f007b0f --- /dev/null +++ b/src/plugins/ifw/ifw.h @@ -0,0 +1,48 @@ +#ifndef IFW_H +#define IFW_H + +#include "plugin.h" + +#define IFW_DBUS_PATH PLUGIN_ROOT_PATH "/ifw" +#define IFW_DBUS_INTERFACE PLUGIN_ROOT_INTF ".ifw" + +#include <sys/types.h> +#include "libnl_ifw.h" + +#define IFW_SYSCONF_ROOT "/etc/ifw/" +#define IFW_BLACKLIST_FILENAME IFW_SYSCONF_ROOT "blacklist" +#define IFW_WHITELIST_FILENAME IFW_SYSCONF_ROOT "whitelist" + +typedef enum { + IFW_MODE_AUTO, + IFW_MODE_INTERACTIVE +} ifw_mode_t; + +typedef struct { + long timestamp_sec; /* date */ + char indev_name[IFNAMSIZ]; /* input interface */ + char prefix[PREFSIZ]; /* summary of attack */ + int sensor; /* sensor the alert come from */ + int protocol; /* Protocol */ + u_int32_t s_addr; /* source address */ + u_int16_t d_port; /* destination port UDP/TCP */ + u_int8_t icmp_type; /* icmp type */ +} msg_usr_t; + +typedef struct popup_verdict { + int seq; + int bl; +} popup_verdict_t; + +#include "black_list.h" +#include "white_list.h" +#include "report_list.h" + +typedef struct { + ifw_mode_t mode; + black_list_t blacklist; + report_list_t reports; + white_list_t whitelist; +} ifw_t; + +#endif /* IFW_H */ diff --git a/src/plugins/ifw/ifw_dbus.c b/src/plugins/ifw/ifw_dbus.c new file mode 100644 index 0000000..82b2675 --- /dev/null +++ b/src/plugins/ifw/ifw_dbus.c @@ -0,0 +1,456 @@ +#include <stdio.h> + +#include "ifw_dbus.h" + +static void ifw_dbus_notify_simple_signal(DBusConnection *bus, char *signal) { + DBusMessage *message; + + message = dbus_message_new_signal(IFW_DBUS_PATH, + IFW_DBUS_INTERFACE, + signal); + dbus_connection_send(bus, message, NULL); + dbus_connection_flush(bus); + dbus_message_unref(message); +} + +void ifw_dbus_apply_report_verdict(DBusConnection *connection, ifw_t *ifw, report_list_cell_t *report, int do_blacklist) { + if (do_blacklist) { + if (!black_list_find(&ifw->blacklist, report->info.s_addr)) { + printf("blacklisting seq %d\n", report->seq); + black_list_add(&ifw->blacklist, &report->info); + ifw_dbus_notify_blacklist(connection, &report->info); + } else { + printf("(seq %d) addr %u already in blacklist\n", report->seq, report->info.s_addr); + } + } else { + printf("ignoring seq %d\n", report->seq); + } + report->processed = 1; +} + +/* notify frontends of a new attack with a DBus signal */ +void ifw_dbus_notify_attack(DBusConnection *bus, report_list_cell_t *report) { + DBusMessage *message; + + message = dbus_message_new_signal(IFW_DBUS_PATH, + IFW_DBUS_INTERFACE, + "Attack"); + + dbus_message_append_args(message, + DBUS_TYPE_UINT32, + report->info.timestamp_sec, + DBUS_TYPE_STRING, + report->info.indev_name, + DBUS_TYPE_STRING, + report->info.prefix, + DBUS_TYPE_UINT32, + report->info.sensor, + DBUS_TYPE_UINT32, + report->info.protocol, + DBUS_TYPE_UINT32, + report->info.s_addr, + DBUS_TYPE_UINT32, + report->info.d_port, + DBUS_TYPE_UINT32, + report->info.icmp_type, + DBUS_TYPE_UINT32, + report->seq, + DBUS_TYPE_UINT32, + report->processed, + DBUS_TYPE_INVALID); + dbus_connection_send(bus, message, NULL); + dbus_connection_flush(bus); + dbus_message_unref(message); +} + +/* notify frontends of a new blacklist with a DBus signal */ +void ifw_dbus_notify_blacklist(DBusConnection *bus, msg_usr_t *attack) { + DBusMessage *message; + + message = dbus_message_new_signal(IFW_DBUS_PATH, + IFW_DBUS_INTERFACE, + "Blacklist"); + + dbus_message_append_args(message, + DBUS_TYPE_UINT32, + attack->timestamp_sec, + DBUS_TYPE_STRING, + attack->indev_name, + DBUS_TYPE_STRING, + attack->prefix, + DBUS_TYPE_UINT32, + attack->sensor, + DBUS_TYPE_UINT32, + attack->protocol, + DBUS_TYPE_UINT32, + attack->s_addr, + DBUS_TYPE_UINT32, + attack->d_port, + DBUS_TYPE_UINT32, + attack->icmp_type, + DBUS_TYPE_INVALID); + dbus_connection_send(bus, message, NULL); + dbus_connection_flush(bus); + dbus_message_unref(message); +} + +/* notify frontends of a new whitelist with a DBus signal */ +void ifw_dbus_notify_whitelist(DBusConnection *bus, u_int32_t addr) { + DBusMessage *message; + + message = dbus_message_new_signal(IFW_DBUS_PATH, + IFW_DBUS_INTERFACE, + "Whitelist"); + dbus_message_append_args(message, + DBUS_TYPE_UINT32, + addr, + DBUS_TYPE_INVALID); + dbus_connection_send(bus, message, NULL); + dbus_connection_flush(bus); + dbus_message_unref(message); +} + +/* notify frontends that ifw data isn't usable with a DBus signal */ +void ifw_dbus_notify_clear(DBusConnection *bus) { + ifw_dbus_notify_simple_signal(bus, "Clear"); +} + +/* notify frontends that ifw has just been started */ +void ifw_dbus_notify_init(DBusConnection *bus) { + ifw_dbus_notify_simple_signal(bus, "Init"); +} + +/* notify frontends that a user is aware of the attacks */ +void ifw_dbus_notify_alert_ack(DBusConnection *bus) { + ifw_dbus_notify_simple_signal(bus, "AlertAck"); +} + +/* notify frontends that a user is wants to review the attacks */ +void ifw_dbus_notify_manage_request(DBusConnection *bus) { + ifw_dbus_notify_simple_signal(bus, "ManageRequest"); +} + +DBusHandlerResult ifw_dbus_get_mode(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusMessage *reply; + + reply = dbus_message_new_method_return(message); + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, + ifw->mode, + DBUS_TYPE_INVALID); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_set_mode(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + DBusMessage *reply; + ifw_mode_t mode; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &mode, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_set_mode(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + printf("setting new ifw mode : %s\n", mode == IFW_MODE_AUTO ? "auto" : mode == IFW_MODE_INTERACTIVE ? "interactive" : "unknown"); + ifw->mode = mode; + + reply = dbus_message_new_method_return(message); + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, + ifw->mode, + DBUS_TYPE_INVALID); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_get_reports(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + struct list_head *entry; + DBusMessage *reply; + char include_processed; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &include_processed, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_get_reports(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + reply = dbus_message_new_method_return(message); + __list_for_each(entry, &ifw->reports) { + report_list_cell_t *cell; + cell = list_entry(entry, report_list_cell_t, list); + if (cell->processed && !include_processed) { + continue; + } + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, + cell->info.timestamp_sec, + DBUS_TYPE_STRING, + cell->info.indev_name, + DBUS_TYPE_STRING, + cell->info.prefix, + DBUS_TYPE_UINT32, + cell->info.sensor, + DBUS_TYPE_UINT32, + cell->info.protocol, + DBUS_TYPE_UINT32, + cell->info.s_addr, + DBUS_TYPE_UINT32, + cell->info.d_port, + DBUS_TYPE_UINT32, + cell->info.icmp_type, + DBUS_TYPE_UINT32, + cell->seq, + DBUS_TYPE_UINT32, + cell->processed, + DBUS_TYPE_INVALID); + } + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_get_blacklist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + struct list_head *entry; + DBusMessage *reply; + + reply = dbus_message_new_method_return(message); + __list_for_each(entry, &ifw->blacklist) { + black_list_cell_t *cell; + cell = list_entry(entry, black_list_cell_t, list); + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, + cell->info.timestamp_sec, + DBUS_TYPE_STRING, + cell->info.indev_name, + DBUS_TYPE_STRING, + cell->info.prefix, + DBUS_TYPE_UINT32, + cell->info.sensor, + DBUS_TYPE_UINT32, + cell->info.protocol, + DBUS_TYPE_UINT32, + cell->info.s_addr, + DBUS_TYPE_UINT32, + cell->info.d_port, + DBUS_TYPE_UINT32, + cell->info.icmp_type, + DBUS_TYPE_INVALID); + } + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_set_blacklist_verdict(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + DBusMessage *reply; + int seq, do_blacklist; + report_list_cell_t *report; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &seq, + DBUS_TYPE_UINT32, + &do_blacklist, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_blacklist(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + report = report_list_find_seq(&ifw->reports, seq); + if (report) { + ifw_dbus_apply_report_verdict(connection, ifw, report, do_blacklist); + } else { + fprintf(stderr, "unable find sequence number in report list, skipping\n"); + } + + black_list_print(&ifw->blacklist); + report_list_print(&ifw->reports); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_unblacklist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + DBusMessage *reply; + u_int32_t addr; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &addr, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_blacklist(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + black_list_remove(&ifw->blacklist, addr); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_get_whitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + struct list_head *entry; + DBusMessage *reply; + + reply = dbus_message_new_method_return(message); + __list_for_each(entry, &ifw->whitelist) { + white_list_cell_t *cell; + cell = list_entry(entry, white_list_cell_t, list); + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, + cell->addr, + DBUS_TYPE_INVALID); + } + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_whitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + DBusMessage *reply; + u_int32_t addr; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &addr, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_whitelist(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + if (!white_list_find(&ifw->whitelist, addr)) { + printf("whitelisting addr %u\n", addr); + white_list_add(&ifw->whitelist, addr); + } else { + printf("addr %u already in whitelist\n", addr); + } + white_list_print(&ifw->whitelist); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + ifw_dbus_notify_whitelist(connection, addr); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_unwhitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusError error; + DBusMessage *reply; + u_int32_t addr; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, + &error, + DBUS_TYPE_UINT32, + &addr, + DBUS_TYPE_INVALID)) { + fprintf(stderr, "ifw_dbus_whitelist(): failed to read D-BUS message args: %s\n", error.message); + dbus_error_free (&error); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + dbus_error_free (&error); + + printf("remove addr from whitelist %u\n", addr); + white_list_remove(&ifw->whitelist, addr); + + white_list_print(&ifw->whitelist); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_clear_processed_reports(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusMessage *reply; + + report_list_clear_processed(&ifw->reports); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_send_alert_ack(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusMessage *reply; + + ifw_dbus_notify_alert_ack(connection); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +DBusHandlerResult ifw_dbus_send_manage_request(DBusConnection *connection, DBusMessage *message, ifw_t *ifw) { + DBusMessage *reply; + + ifw_dbus_notify_manage_request(connection); + + reply = dbus_message_new_method_return(message); + dbus_connection_send(connection, reply, NULL); + dbus_connection_flush(connection); + dbus_message_unref(reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} diff --git a/src/plugins/ifw/ifw_dbus.h b/src/plugins/ifw/ifw_dbus.h new file mode 100644 index 0000000..a4385db --- /dev/null +++ b/src/plugins/ifw/ifw_dbus.h @@ -0,0 +1,43 @@ +#ifndef IFW_DBUS_H +#define IFW_DBUS_H + +#include <dbus/dbus.h> +#include "ifw.h" + +void ifw_dbus_apply_report_verdict(DBusConnection *connection, ifw_t *ifw, report_list_cell_t *report, int do_blacklist); + +/* notify frontends of a new attack with a DBus signal */ +void ifw_dbus_notify_attack(DBusConnection *bus, report_list_cell_t *report); + +/* notify frontends of a new whitelist with a DBus signal */ +void ifw_dbus_notify_whitelist(DBusConnection *bus, u_int32_t addr); + +/* notify frontends of a new blacklist with a DBus signal */ +void ifw_dbus_notify_blacklist(DBusConnection *bus, msg_usr_t *attack); + +/* notify frontends that ifw data isn't usable with a DBus signal */ +void ifw_dbus_notify_clear(DBusConnection *bus); + +/* notify frontends that ifw has just been started */ +void ifw_dbus_notify_init(DBusConnection *bus); + +/* notify frontends that a user is aware of the attacks */ +void ifw_dbus_notify_alert_ack(DBusConnection *bus); + +/* notify frontends that a user is wants to review the attacks */ +void ifw_dbus_notify_manage_request(DBusConnection *bus); + +DBusHandlerResult ifw_dbus_get_mode(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_set_mode(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_get_reports(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_get_blacklist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_set_blacklist_verdict(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_unblacklist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_get_whitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_whitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_unwhitelist(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_clear_processed_reports(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_send_alert_ack(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); +DBusHandlerResult ifw_dbus_send_manage_request(DBusConnection *connection, DBusMessage *message, ifw_t *ifw); + +#endif /* IFW_DBUS_H */ diff --git a/src/plugins/ifw/ipset.c b/src/plugins/ifw/ipset.c new file mode 100644 index 0000000..74ca06e --- /dev/null +++ b/src/plugins/ifw/ipset.c @@ -0,0 +1,89 @@ +#include "ipset.h" + +#include <stdio.h> +#include <stdlib.h> +#include <netinet/in.h> + +#define CMD_MAX_SIZE 1024 + +#ifdef IPSET_DEBUG +#define DPRINTF(s) printf("%s\n", s) +#else +#define DPRINTF(s) +#endif + +void ipset_init() { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -N " IPSET_BLACKLIST_NAME " iptree --timeout " IPSET_BLACKLIST_TIMEOUT); + DPRINTF(cmd); + system(cmd); + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -N " IPSET_WHITELIST_NAME " iptree"); + DPRINTF(cmd); + system(cmd); +} + +void ipset_destroy() { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -X " IPSET_BLACKLIST_NAME); + DPRINTF(cmd); + system(cmd); + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -X " IPSET_WHITELIST_NAME); + DPRINTF(cmd); + system(cmd); +} + +/* void ipset_blacklist_load(char *filename) { */ +/* char cmd[CMD_MAX_SIZE]; */ +/* snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -R < %s", filename); */ +/* DPRINTF(cmd); */ +/* system(cmd); */ +/* } */ + +/* void ipset_blacklist_save(char *filename) { */ +/* char cmd[CMD_MAX_SIZE]; */ +/* snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -S " IPSET_BLACKLIST_NAME " > %s", filename); */ +/* DPRINTF(cmd); */ +/* system(cmd); */ +/* } */ + +/* void ipset_whitelist_load(char *filename) { */ +/* char cmd[CMD_MAX_SIZE]; */ +/* snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -R < %s", filename); */ +/* DPRINTF(cmd); */ +/* system(cmd); */ +/* } */ + +/* void ipset_whitelist_save(char *filename) { */ +/* char cmd[CMD_MAX_SIZE]; */ +/* snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -S " IPSET_WHITELIST_NAME " > %s", filename); */ +/* DPRINTF(cmd); */ +/* system(cmd); */ +/* } */ + +void ipset_blacklist_add(u_int32_t addr) { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -A " IPSET_BLACKLIST_NAME " %u", ntohl(addr)); + DPRINTF(cmd); + system(cmd); +} + +void ipset_blacklist_remove(u_int32_t addr) { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -D " IPSET_BLACKLIST_NAME " %u", ntohl(addr)); + DPRINTF(cmd); + system(cmd); +} + +void ipset_whitelist_add(u_int32_t addr) { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -A " IPSET_WHITELIST_NAME " %u", ntohl(addr)); + DPRINTF(cmd); + system(cmd); +} + +void ipset_whitelist_remove(u_int32_t addr) { + char cmd[CMD_MAX_SIZE]; + snprintf(cmd, CMD_MAX_SIZE, IPSET_CMD " -D " IPSET_WHITELIST_NAME " %u", ntohl(addr)); + DPRINTF(cmd); + system(cmd); +} diff --git a/src/plugins/ifw/ipset.h b/src/plugins/ifw/ipset.h new file mode 100644 index 0000000..a78395a --- /dev/null +++ b/src/plugins/ifw/ipset.h @@ -0,0 +1,22 @@ +#ifndef IPSET_H +#define IPSET_H + +#define IPSET_CMD "ipset" +#define IPSET_BLACKLIST_NAME "ifw_bl" +#define IPSET_WHITELIST_NAME "ifw_wl" +#define IPSET_BLACKLIST_TIMEOUT "3600" + +#include <sys/types.h> + +void ipset_init(); +void ipset_destroy(); +/* void ipset_blacklist_load(char *filename); */ +/* void ipset_blacklist_save(char *filename); */ +/* void ipset_whitelist_load(char *filename); */ +/* void ipset_whitelist_save(char *filename); */ +void ipset_blacklist_add(u_int32_t addr); +void ipset_blacklist_remove(u_int32_t addr); +void ipset_whitelist_add(u_int32_t addr); +void ipset_whitelist_remove(u_int32_t addr); + +#endif /* IPSET_H */ diff --git a/src/plugins/ifw/libnl_ifw.c b/src/plugins/ifw/libnl_ifw.c new file mode 100644 index 0000000..bb41363 --- /dev/null +++ b/src/plugins/ifw/libnl_ifw.c @@ -0,0 +1,62 @@ +/* nl_create_socket(), nl_bind_socket() and nl_read_msg() + * for Interactive Firewall + * sbellabes@mandriva.com + */ + + +#include <asm/types.h> +#include <sys/socket.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> + +#include "libnl_ifw.h" + +int nl_ifw_bind_socket(int s) { + struct sockaddr_nl saddr_nl; + int res; + + memset(&saddr_nl, 0, sizeof(struct sockaddr_nl)); + saddr_nl.nl_family = AF_NETLINK; + saddr_nl.nl_pid = getpid(); + saddr_nl.nl_groups = 10; + + res = bind(s, (struct sockaddr *)&saddr_nl, sizeof(saddr_nl)); + if (res == -1) { + perror("nl_bind_socket"); + return -1; + } + return 1; +} + +int nl_ifw_create_socket(void) { + int s; + + s = socket(PF_NETLINK, SOCK_RAW, NETLINK_IFWLOG); + if (s < 0) { + perror("nl_create_socket"); + return -1; + } + + if (nl_ifw_bind_socket(s) < 0) { + close(s); + fprintf(stderr, "bind failed\n"); + return -1; + } + + return s; +} + +int nl_ifw_read_msg(int s, struct nlmsghdr *nlh, struct nl_msg *msg) { + char buf[sizeof(struct nlmsghdr) + sizeof(struct nl_msg)]; + int ret; + + ret = recv(s, &buf, sizeof(buf), 0); + if (ret > 0) { + if (nlh) memcpy(nlh, buf, sizeof(struct nlmsghdr)); + if (msg) memcpy(msg, NLMSG_DATA(buf), sizeof(struct nl_msg)); + } + + return ret; +} diff --git a/src/plugins/ifw/libnl_ifw.h b/src/plugins/ifw/libnl_ifw.h new file mode 100644 index 0000000..896d05c --- /dev/null +++ b/src/plugins/ifw/libnl_ifw.h @@ -0,0 +1,35 @@ +/* + * libnl_ifw.h + */ + +#ifndef _LIBNL_IFW_H +#define _LIBNL_IFW_H + +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <linux/if.h> +#include <linux/netlink.h> + +#define NETLINK_IFWLOG 19 + +#define PREFSIZ 32 + +struct nl_msg { /* Netlink kernel to user message */ + long timestamp_sec; /* time packet */ + char indev_name[IFNAMSIZ]; /* name of the ingoing interface */ + char outdev_name[IFNAMSIZ]; /* name of the outgoing interface */ + unsigned char prefix[PREFSIZ]; /* logging informations */ + struct iphdr ip; + union { + struct tcphdr th; + struct udphdr uh; + } h; +}; + +int nl_ifw_bind_socket(int s); +int nl_ifw_create_socket(void); +int nl_ifw_read_msg(int s, struct nlmsghdr *nlh, struct nl_msg *msg); + +#endif /* !_LIBNL_IFW_H */ diff --git a/src/plugins/ifw/list.h b/src/plugins/ifw/list.h new file mode 100644 index 0000000..1b55f95 --- /dev/null +++ b/src/plugins/ifw/list.h @@ -0,0 +1,155 @@ +#ifndef LIST_H +#define LIST_H + +/* borrowed from kernel header linux/list.h */ + +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +/* borrowed from kernel header linux/kernel.h */ + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - linux_offsetof(type,member) );}) + + +/* borrowed from linux/stdddef.h */ + +#define linux_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#endif /* LIST_H */ diff --git a/src/plugins/ifw/plugin.c b/src/plugins/ifw/plugin.c new file mode 100644 index 0000000..0e6ac69 --- /dev/null +++ b/src/plugins/ifw/plugin.c @@ -0,0 +1,224 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +#include "ifw.h" +#include "ifw_dbus.h" +#include "ipset.h" + +static int init(plugin_t *plugin, DBusConnection *connection); +static void deinit(plugin_t *plugin, DBusConnection *connection); +static void process_attack(plugin_t *plugin, DBusConnection *connection, int seq, msg_usr_t *attack); +static DBusHandlerResult handle_message(DBusConnection *connection, DBusMessage *message, plugin_t *plugin); +#ifdef IFW_FAKE +static int generate_fake_attack(msg_usr_t *attack); +static void handle_fake(plugin_t *plugin, DBusConnection *connection); +#else +static void handle_incoming(plugin_t *plugin, DBusConnection *connection); +#endif + +static int init(plugin_t *plugin, DBusConnection *connection) { + ifw_t *ifw; + + ifw = malloc(sizeof(ifw_t)); + if (!ifw) { + fprintf(stderr, "unable to malloc ifw\n"); + return -1; + } + + report_list_init(&ifw->reports); + black_list_init(&ifw->blacklist); + white_list_init(&ifw->whitelist); + white_list_load(&ifw->whitelist, IFW_WHITELIST_FILENAME); + + ifw->mode = IFW_MODE_INTERACTIVE; + +#ifdef IFW_FAKE + plugin->fd = 0; +#else + plugin->fd = nl_ifw_create_socket(); + if (plugin->fd < 0) { + fprintf(stderr, "unable to init netlink\n"); + return -1; + } +#endif + + ifw_dbus_notify_clear(connection); + ifw_dbus_notify_init(connection); + + plugin->priv = (void *) ifw; + + return 0; +} + +static void deinit(plugin_t *plugin, DBusConnection *connection) { + ifw_t *ifw = (ifw_t *) plugin->priv; + + ifw_dbus_notify_clear(connection); + close(plugin->fd); +} + +#ifdef IFW_FAKE +#include <time.h> + +static int generate_fake_attack(msg_usr_t *attack) { + static int seq = 0; + uint32_t addr = 0xC0A86401; + + time(&attack->timestamp_sec); + strcpy(attack->indev_name, "ppp0"); + attack->sensor = 0; + attack->protocol = 0; + attack->icmp_type = 0; + attack->d_port = 0; + attack->s_addr = htonl(addr); + + switch(seq%3) { + case 0: + strcpy(attack->prefix, "SCAN"); + break; + case 1: + strcpy(attack->prefix, "SERV"); + attack->d_port = 22; + break; + case 2: + strcpy(attack->prefix, "PASS"); + break; + } + + addr++; + seq++; + + return seq; +} + +static void handle_fake(plugin_t *plugin, DBusConnection *connection) { + msg_usr_t fake_attack; + int seq; + + read(0, NULL, 1); + + seq = generate_fake_attack(&fake_attack); + printf("seq : %d\n", seq); + + process_attack(plugin, connection, seq, &fake_attack); +} + +#else + +static void handle_incoming(plugin_t *plugin, DBusConnection *connection) { + struct nl_msg msg; + static int seq = 0; + msg_usr_t attack; + + if (nl_ifw_read_msg(plugin->fd, NULL, &msg) <= 0) { + fprintf(stderr, "unable to read packet from netlink\n"); + return; + } + + attack.timestamp_sec = msg.timestamp_sec; + strncpy(attack.indev_name, msg.indev_name, IFNAMSIZ); + strncpy(attack.prefix, (char *) msg.prefix, PREFSIZ); + attack.sensor = 0; + attack.protocol = msg.ip.protocol; + attack.s_addr = msg.ip.saddr; + switch (msg.ip.protocol) { + case IPPROTO_TCP: + attack.d_port = msg.h.th.dest; + break; + case IPPROTO_UDP: + attack.d_port = msg.h.uh.dest; + break; + default: + attack.d_port = 0; + break; + } + attack.icmp_type = 0; + + process_attack(plugin, connection, seq++, &attack); +} + +#endif + +static void process_attack(plugin_t *plugin, DBusConnection *connection, int seq, msg_usr_t *attack) { + ifw_t *ifw = (ifw_t *) plugin->priv; + report_list_cell_t *report; + + if (black_list_find(&ifw->blacklist, attack->s_addr) || + white_list_find(&ifw->whitelist, attack->s_addr) || + report_list_find(&ifw->reports, attack->s_addr, 0)) { + struct in_addr addr; + addr.s_addr = attack->s_addr; + fprintf(stderr, "skipping known address: %s\n", inet_ntoa(addr)); + return; + } + + if (!strcmp(attack->indev_name, "lo")) { + fprintf(stderr, "skipping loopback interface\n"); + return; + } + + report = report_list_add(&ifw->reports, seq, attack); + if (report) { + if (ifw->mode == IFW_MODE_AUTO) { + /* add ip address in ipset blacklist */ + ifw_dbus_apply_report_verdict(connection, ifw, report, 1); + } + + /* notify the attack to frontends */ + ifw_dbus_notify_attack(connection, report); + } + + black_list_print(&ifw->blacklist); + white_list_print(&ifw->whitelist); + report_list_print(&ifw->reports); +} + +static DBusHandlerResult handle_message(DBusConnection *connection, DBusMessage *message, plugin_t *plugin) { + ifw_t *ifw = (ifw_t *) plugin->priv; + if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "GetMode")) { + return ifw_dbus_get_mode(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "SetMode")) { + return ifw_dbus_set_mode(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "GetReports")) { + return ifw_dbus_get_reports(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "GetBlacklist")) { + return ifw_dbus_get_blacklist(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "SetBlacklistVerdict")) { + return ifw_dbus_set_blacklist_verdict(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "UnBlacklist")) { + return ifw_dbus_unblacklist(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "GetWhitelist")) { + return ifw_dbus_get_whitelist(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "Whitelist")) { + return ifw_dbus_whitelist(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "UnWhitelist")) { + return ifw_dbus_unwhitelist(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "ClearProcessedReports")) { + return ifw_dbus_clear_processed_reports(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "SendAlertAck")) { + return ifw_dbus_send_alert_ack(connection, message, ifw); + } else if (dbus_message_is_method_call(message, IFW_DBUS_INTERFACE, "SendManageRequest")) { + return ifw_dbus_send_manage_request(connection, message, ifw); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +plugin_t ifw_plugin = { + .name = "Interactive Firewall", + .path = IFW_DBUS_PATH, + .init = init, +#ifdef IFW_FAKE + .handle_incoming = handle_fake, +#else + .handle_incoming = handle_incoming, +#endif + .handle_message = handle_message, + .deinit = deinit, +}; diff --git a/src/plugins/ifw/report_list.c b/src/plugins/ifw/report_list.c new file mode 100644 index 0000000..c21df7e --- /dev/null +++ b/src/plugins/ifw/report_list.c @@ -0,0 +1,81 @@ +#include "report_list.h" + +#include <stdio.h> +#include <stdlib.h> + +void report_list_init(report_list_t *list) { + INIT_LIST_HEAD(list); +} + +report_list_cell_t *report_list_add(report_list_t *list, int seq, msg_usr_t *attack) { + report_list_cell_t *cell; + + cell = malloc(sizeof(report_list_cell_t)); + if (!cell) { + fprintf(stderr, "unable to alloc enough memory for report list cell, skipping\n"); + return NULL; + } + cell->seq = seq; + cell->info = *attack; + cell->processed = 0; + INIT_LIST_HEAD(&cell->list); + list_add_tail(&cell->list, list); + + return cell; +} + +report_list_cell_t *report_list_find(report_list_t *list, u_int32_t addr, int include_processed) { + struct list_head *entry; + + __list_for_each(entry, list) { + report_list_cell_t *cell; + cell = list_entry(entry, report_list_cell_t, list); + if (cell->info.s_addr == addr && include_processed || !cell->processed) { + return cell; + } + } + + return NULL; +} + +report_list_cell_t *report_list_find_seq(report_list_t *list, int seq) { + struct list_head *entry; + + __list_for_each(entry, list) { + report_list_cell_t *cell; + cell = list_entry(entry, report_list_cell_t, list); + if (cell->seq == seq) { + return cell; + } + } + + return NULL; +} + +void report_list_remove(report_list_cell_t *cell) { + list_del(&cell->list); + free(cell); +} + +void report_list_clear_processed(report_list_t *list) { + report_list_cell_t *cell, *n; + + list_for_each_entry_safe(cell, n, list, list) { + if (cell->processed) { + report_list_remove(cell); + } + } +} + +void report_list_print(report_list_t *list) { + struct list_head *entry; + + printf("* report list {\n"); + __list_for_each(entry, list) { + report_list_cell_t *cell; + cell = list_entry(entry, report_list_cell_t, list); + printf("%d,\n", cell->seq); + } + printf("} report list *\n"); +} + diff --git a/src/plugins/ifw/report_list.h b/src/plugins/ifw/report_list.h new file mode 100644 index 0000000..626afed --- /dev/null +++ b/src/plugins/ifw/report_list.h @@ -0,0 +1,24 @@ +#ifndef REPORT_LIST_H +#define REPORT_LIST_H + +#include "list.h" +typedef struct list_head report_list_t; + +#include "ifw.h" + +typedef struct { + struct list_head list; + int seq; + msg_usr_t info; + char processed; +} report_list_cell_t; + +void report_list_init(report_list_t *list); +report_list_cell_t *report_list_add(report_list_t *list, int seq, msg_usr_t *attack); +report_list_cell_t *report_list_find(report_list_t *list, u_int32_t addr, int include_processed); +report_list_cell_t *report_list_find_seq(report_list_t *list, int seq); +void report_list_remove(report_list_cell_t *cell); +void report_list_clear_processed(report_list_t *list); +void report_list_print(report_list_t *list); + +#endif /* REPORT_LIST_H */ diff --git a/src/plugins/ifw/white_list.c b/src/plugins/ifw/white_list.c new file mode 100644 index 0000000..4318abc --- /dev/null +++ b/src/plugins/ifw/white_list.c @@ -0,0 +1,119 @@ +#include "white_list.h" +#include "ipset.h" +#include "ifw.h" + +#include <stdio.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> + +void white_list_init(white_list_t *list) { + INIT_LIST_HEAD(list); +} + +void white_list_add(white_list_t *list, u_int32_t addr) { + white_list_cell_t *cell; + + cell = malloc(sizeof(white_list_cell_t)); + if (!cell) { + fprintf(stderr, "unable to alloc enough memory for white list cell, skipping\n"); + return; + } + cell->addr = addr; + INIT_LIST_HEAD(&cell->list); + list_add_tail(&cell->list, list); + + ipset_whitelist_add(cell->addr); + white_list_save(list, IFW_WHITELIST_FILENAME); +} + +white_list_cell_t *white_list_find(white_list_t *list, u_int32_t addr) { + struct list_head *entry; + + __list_for_each(entry, list) { + white_list_cell_t *cell; + cell = list_entry(entry, white_list_cell_t, list); + if (cell->addr == addr) { + return cell; + } + } + + return NULL; +} + +void white_list_remove(white_list_t *list, u_int32_t addr) { + white_list_cell_t *cell, *n, *prev; + + ipset_whitelist_remove(addr); + + prev = NULL; + list_for_each_entry_safe(cell, n, list, list) { + if (prev) + free(prev); + if (cell->addr == addr) { + list_del(&cell->list); + prev = cell; + } else { + prev = NULL; + } + } + if (prev) + free(prev); + + white_list_save(list, IFW_WHITELIST_FILENAME); +} + + +void white_list_print(white_list_t *list) { + struct list_head *entry; + + printf("* white list {\n"); + __list_for_each(entry, list) { + white_list_cell_t *cell; + struct in_addr addr; + cell = list_entry(entry, white_list_cell_t, list); + addr.s_addr = cell->addr; + printf("%s,\n", inet_ntoa(addr)); + } + printf("} white list *\n"); +} + +void white_list_load(white_list_t *list, const char *filepath) { + FILE *fp; + + fp = fopen(filepath, "r"); + if (fp) { + char addr_str[16]; + struct in_addr addr; + while (fscanf(fp, "%15s\n", addr_str) > 0) { + if (inet_aton(addr_str, &addr)) { + white_list_add(list, addr.s_addr); + printf("adding IP address in white list: %s\n", addr_str); + } else { + fprintf(stderr, "unable to parse IP address in white list: %s\n", addr_str); + } + } + } else { + fprintf(stderr, "unable to open white list file\n"); + } +} + +void white_list_save(white_list_t *list, const char *filepath) { + FILE *fp; + struct list_head *entry; + + fp = fopen(filepath, "w+"); + if (fp) { + __list_for_each(entry, list) { + white_list_cell_t *cell; + struct in_addr addr; + cell = list_entry(entry, white_list_cell_t, list); + addr.s_addr = cell->addr; + fprintf(fp, "%15s\n", inet_ntoa(addr)); + printf("adding IP address in white list: %s\n", inet_ntoa(addr)); + } + } else { + fprintf(stderr, "unable to write white list file\n"); + } +} diff --git a/src/plugins/ifw/white_list.h b/src/plugins/ifw/white_list.h new file mode 100644 index 0000000..564f5ee --- /dev/null +++ b/src/plugins/ifw/white_list.h @@ -0,0 +1,23 @@ +#ifndef WHITE_LIST_H +#define WHITE_LIST_H + +#include "list.h" + +#include <sys/types.h> + +typedef struct list_head white_list_t; + +typedef struct { + struct list_head list; + u_int32_t addr; +} white_list_cell_t; + +void white_list_init(white_list_t *list); +void white_list_add(white_list_t *list, u_int32_t addr); +white_list_cell_t *white_list_find(white_list_t *list, u_int32_t addr); +void white_list_remove(white_list_t *list, u_int32_t addr); +void white_list_print(white_list_t *list); +void white_list_load(white_list_t *list, const char *filepath); +void white_list_save(white_list_t *list, const char *filepath); + +#endif /* WHITE_LIST_H */ |