1 #include <switch.h>
2 
3 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fail2ban_shutdown);
4 SWITCH_MODULE_LOAD_FUNCTION(mod_fail2ban_load);
5 
6 SWITCH_MODULE_DEFINITION(mod_fail2ban, mod_fail2ban_load, mod_fail2ban_shutdown, NULL);
7 
8 static struct {
9 	switch_memory_pool_t *modpool;
10 	switch_file_t *logfile;
11 	char *logfile_name;
12 } globals = {0};
13 
14 
mod_fail2ban_do_config(void)15 static switch_status_t mod_fail2ban_do_config(void)
16 {
17 	switch_status_t status = SWITCH_STATUS_SUCCESS;
18 	char *cf = "fail2ban.conf";
19 	switch_xml_t cfg, xml, bindings_tag, config = NULL, param = NULL;
20 	char *var = NULL, *val = NULL;
21 
22 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "setting configs\n");
23 
24 	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
25 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
26 		return SWITCH_STATUS_TERM;
27 	}
28 
29 	if (!(bindings_tag = switch_xml_child(cfg, "bindings"))) {
30 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing <bindings> tag!\n");
31 		goto done;
32 	}
33 
34 	for (config = switch_xml_child(bindings_tag, "config"); config; config = config->next) {
35 
36 		for (param = switch_xml_child(config, "param"); param; param = param->next) {
37 			var = (char *) switch_xml_attr_soft(param, "name");
38 			val = (char *) switch_xml_attr_soft(param, "value");
39 
40 			if (strncmp(var,"logfile", 7) == 0) {
41 			  if (zstr(val)) {
42 			    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Null or empty Logfile attribute %s: %s\n", var, val);
43 			  } else {
44 			    globals.logfile_name = switch_core_strdup(globals.modpool, val);
45 			  }
46 			} else {
47 			  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown attribute %s: %s\n", var, val);
48 			}
49 		}
50 	}
51 	if ( zstr(globals.logfile_name) ) {
52 	  globals.logfile_name = switch_core_sprintf(globals.modpool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, "fail2ban.log");
53 	}
54 
55 	if ((status = switch_file_open(&globals.logfile, globals.logfile_name, SWITCH_FOPEN_WRITE|SWITCH_FOPEN_APPEND|SWITCH_FOPEN_CREATE, SWITCH_FPROT_OS_DEFAULT, globals.modpool)) != SWITCH_STATUS_SUCCESS) {
56 	  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to open %s\n", globals.logfile_name);
57 	  status = SWITCH_STATUS_FALSE;
58 	}
59 
60  done:
61 	switch_xml_free(xml);
62 
63 	return SWITCH_STATUS_SUCCESS;
64 }
65 
fail2ban_logger(const char * message,char * user,char * ip)66 static int fail2ban_logger(const char *message, char *user, char *ip)
67 {
68 	switch_time_exp_t tm;
69 	if (!globals.logfile) {
70 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not print to fail2ban log!\n");
71 		return -1;
72 	}
73 
74 	switch_time_exp_lt(&tm, switch_micro_time_now());
75 	return switch_file_printf(globals.logfile, "%s user[%s] ip[%s] at[%04u-%02u-%02uT%02u:%02u:%02u.%06u%+03d%02d]\n", message, user, ip,
76 								tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
77 								tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_gmtoff / 3600, tm.tm_gmtoff % 3600);
78 }
79 
fail2ban_event_handler(switch_event_t * event)80 static void fail2ban_event_handler(switch_event_t *event)
81 {
82 	if (event->event_id == SWITCH_EVENT_CUSTOM && event->subclass_name) {
83 		if (strncmp(event->subclass_name, "sofia::register_attempt",23) == 0) {
84 			fail2ban_logger("A registration was attempted", switch_event_get_header(event, "to-user"), switch_event_get_header(event, "network-ip"));
85 		} else if (strncmp(event->subclass_name, "sofia::register_failure",23) == 0) {
86 			fail2ban_logger("A registration failed", switch_event_get_header(event, "to-user"), switch_event_get_header(event, "network-ip"));
87 		} else if (strncmp(event->subclass_name, "sofia::wrong_call_state",23) == 0) {
88 			fail2ban_logger("Abandoned call from ", switch_event_get_header(event, "from_user"), switch_event_get_header(event, "network_ip"));
89 		}
90 	}
91 }
92 
SWITCH_MODULE_LOAD_FUNCTION(mod_fail2ban_load)93 SWITCH_MODULE_LOAD_FUNCTION(mod_fail2ban_load)
94 {
95 	switch_status_t status;
96 	void *user_data = NULL;
97 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
98 	globals.modpool = pool;
99 
100 	if (mod_fail2ban_do_config() != SWITCH_STATUS_SUCCESS) {
101 		return SWITCH_STATUS_FALSE;
102 	}
103 
104 	if ((status = switch_event_bind(modname, SWITCH_EVENT_CUSTOM, SWITCH_EVENT_SUBCLASS_ANY, fail2ban_event_handler, user_data)) != SWITCH_STATUS_SUCCESS) {
105 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "event bind failed\n");
106 		return SWITCH_STATUS_FALSE;
107 	}
108 
109 	switch_file_printf(globals.logfile, "Fail2ban was started\n");
110 	return SWITCH_STATUS_SUCCESS;
111 }
112 
113 
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fail2ban_shutdown)114 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fail2ban_shutdown)
115 {
116 	switch_status_t status;
117 
118 	if (globals.logfile != NULL) {
119 	  switch_file_printf(globals.logfile, "Fail2ban stoping\n");
120 	}
121 
122 	if ((status = switch_event_unbind_callback(fail2ban_event_handler)) != SWITCH_STATUS_SUCCESS) {
123 	  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "event unbind failed\n");
124 	}
125 
126 	if ((status = switch_file_close(globals.logfile)) != SWITCH_STATUS_SUCCESS) {
127 	  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to close %s\n", globals.logfile_name);
128 	}
129 
130 	return status;
131 }
132