diff options
Diffstat (limited to 'src/plugins/ifw/plugin.c')
-rw-r--r-- | src/plugins/ifw/plugin.c | 224 |
1 files changed, 224 insertions, 0 deletions
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, +}; |