diff --git a/policy/protocols/irc/base.bro b/policy/protocols/irc/base.bro index 5dffa34ffc..61ef1b623b 100644 --- a/policy/protocols/irc/base.bro +++ b/policy/protocols/irc/base.bro @@ -64,49 +64,42 @@ function set_session(c: connection) c$irc$ts=network_time(); } -event irc_nick_message(c: connection, who: string, newnick: string) &priority=5 +event irc_nick_message(c: connection, is_orig: bool, who: string, newnick: string) &priority=5 { set_session(c); - - c$irc$command = "NICK"; - c$irc$value = newnick; - } - -event irc_nick_message(c: connection, who: string, newnick: string) &priority=-5 - { - Log::write(IRC, c$irc); - c$irc$nick = newnick; - } - -event irc_user_message(c: connection, user: string, host: string, server: string, real_name: string) &priority=5 - { - set_session(c); - - c$irc$command = "USER"; - c$irc$value = user; - c$irc$addl=fmt("%s %s %s", host, server, real_name); - } - -event irc_user_message(c: connection, user: string, host: string, - server: string, real_name: string) &priority=-5 - { - Log::write(IRC, c$irc); - c$irc$user = user; - } - -event irc_join_message(c: connection, info_list: irc_join_list) &priority=5 - { - set_session(c); - - c$irc$command = "JOIN"; - } - -event irc_join_message(c: connection, info_list: irc_join_list) &priority=-5 - { - for ( l in info_list ) + if ( is_orig ) { - c$irc$value = l$channel; - c$irc$addl = (l$password != "" ? fmt(" with channel key: '%s'", l$password) : ""); + c$irc$command = "NICK"; + c$irc$value = newnick; Log::write(IRC, c$irc); + c$irc$nick = newnick; } - } \ No newline at end of file + } + +event irc_user_message(c: connection, is_orig: bool, user: string, host: string, server: string, real_name: string) &priority=5 + { + set_session(c); + if ( is_orig ) + { + c$irc$command = "USER"; + c$irc$value = user; + c$irc$addl=fmt("%s %s %s", host, server, real_name); + Log::write(IRC, c$irc); + c$irc$user = user; + } + } + +event irc_join_message(c: connection, is_orig: bool, info_list: irc_join_list) &priority=5 + { + set_session(c); + if ( is_orig ) + { + c$irc$command = "JOIN"; + for ( l in info_list ) + { + c$irc$value = l$channel; + c$irc$addl = (l$password != "" ? fmt(" with channel key: '%s'", l$password) : ""); + Log::write(IRC, c$irc); + } + } + } diff --git a/policy/protocols/irc/dcc-send.bro b/policy/protocols/irc/dcc-send.bro index 734aad54fe..aa68b4776a 100644 --- a/policy/protocols/irc/dcc-send.bro +++ b/policy/protocols/irc/dcc-send.bro @@ -9,6 +9,8 @@ ##! PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A @load protocols/irc +@load utils/files +@load utils/numbers module IRC; @@ -59,7 +61,10 @@ event file_transferred(c: connection, prefix: string, descr: string, local fname = generate_extraction_filename(extraction_prefix, c, suffix); irc$extraction_file = open(fname); } - + local tmp = c$irc$command; + c$irc$command = "DCC"; + Log::write(IRC, c$irc); + c$irc$command = tmp; } event file_transferred(c: connection, prefix: string, descr: string, @@ -84,25 +89,18 @@ event file_transferred(c: connection, prefix: string, descr: string, delete dcc_expected_transfers[id$resp_h, id$resp_p]; } - -event irc_server(c: connection, prefix: string, data: string) &priority=5 +event irc_dcc_message(c: connection, is_orig: bool, + prefix: string, target: string, + dcc_type: string, argument: string, + address: addr, dest_port: count, size: count) &priority=5 { - local parts = split_all(data, / /); - local command = parts[1]; - if ( command == "PRIVMSG" && - /[dD][cC][cC] [sS][eE][nN][dD]/ in data && - |parts| > 12 && - /^[0-9]*$/ == parts[|parts|-4] && - /^[0-9]*$/ == parts[|parts|-2] ) - { - c$irc$command = "DCC SEND"; - local ex_h = count_to_v4_addr(extract_count(parts[|parts|-4])); - local ex_p = to_port(to_count(parts[|parts|-2]), tcp); - c$irc$dcc_file_name = parts[|parts|-6]; - c$irc$dcc_file_size = extract_count(parts[|parts|]); - expect_connection(c$id$orig_h, ex_h, ex_p, ANALYZER_FILE, 5 min); - dcc_expected_transfers[ex_h, ex_p] = c$irc; - } + set_session(c); + if ( dcc_type != "SEND" ) return; + c$irc$dcc_file_name = argument; + c$irc$dcc_file_size = size; + local p = to_port(dest_port, tcp); + expect_connection(c$id$orig_h, address, p, ANALYZER_FILE, 5 min); + dcc_expected_transfers[address, p] = c$irc; } event expected_connection_seen(c: connection, a: count) &priority=10 diff --git a/src/IRC.cc b/src/IRC.cc index 04a07d17a9..4456e870d2 100644 --- a/src/IRC.cc +++ b/src/IRC.cc @@ -33,8 +33,8 @@ bool IRC_Analyzer::Available() { // It's a lot of events, but for consistency with other // analyzers we need to check for all of them. - avail = irc_client || irc_server || irc_request || irc_reply || - irc_message || irc_enter_message || irc_quit_message || + avail = irc_request || irc_reply || + irc_message || irc_quit_message || irc_privmsg_message || irc_notice_message || irc_squery_message || irc_join_message || irc_part_message || irc_nick_message || @@ -97,28 +97,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) if ( orig ) - { ProtocolConfirmation(); - if ( irc_client ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(new StringVal(prefix.c_str())); - vl->append(new StringVal(myline.c_str())); - ConnectionEvent(irc_client, vl); - } - } - else - { - if ( irc_server ) - { - val_list* vl = new val_list; - vl->append(BuildConnVal()); - vl->append(new StringVal(prefix.c_str())); - vl->append(new StringVal(myline.c_str())); - ConnectionEvent(irc_server, vl); - } - } int code = 0; string command = ""; @@ -260,6 +239,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new Val(users, TYPE_INT)); vl->append(new Val(services, TYPE_INT)); vl->append(new Val(servers, TYPE_INT)); @@ -296,6 +276,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(type.c_str())); vl->append(new StringVal(channel.c_str())); @@ -338,6 +319,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new Val(users, TYPE_INT)); vl->append(new Val(services, TYPE_INT)); vl->append(new Val(servers, TYPE_INT)); @@ -360,6 +342,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new Val(channels, TYPE_INT)); ConnectionEvent(irc_channel_info, vl); @@ -392,6 +375,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(eop - prefix, prefix)); vl->append(new StringVal(++msg)); ConnectionEvent(irc_global_users, vl); @@ -416,6 +400,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[0].c_str())); vl->append(new StringVal(parts[1].c_str())); vl->append(new StringVal(parts[2].c_str())); @@ -454,6 +439,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[0].c_str())); ConnectionEvent(irc_whois_operator_line, vl); @@ -484,6 +470,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(nick.c_str())); TableVal* set = new TableVal(string_set); for ( unsigned int i = 0; i < parts.size(); ++i ) @@ -519,6 +506,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[1].c_str())); const char* t = topic.c_str(); @@ -552,6 +540,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[0].c_str())); vl->append(new StringVal(parts[1].c_str())); if ( parts[2][0] == '~' ) @@ -579,6 +568,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); ConnectionEvent(irc_invalid_nick, vl); } break; @@ -590,6 +580,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new Val(code == 381, TYPE_BOOL)); ConnectionEvent(irc_oper_response, vl); } @@ -599,6 +590,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) default: val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new Val(code, TYPE_COUNT)); vl->append(new StringVal(params.c_str())); @@ -622,7 +614,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) return; } - else if ( irc_privmsg_message && command == "PRIVMSG") + else if ( irc_privmsg_message || irc_dcc_message && command == "PRIVMSG") { unsigned int pos = params.find(' '); if ( pos >= params.size() ) @@ -649,8 +641,12 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) vector parts = SplitWords(message, ' '); if ( parts.size() < 5 || parts.size() > 6 ) { - Weird("irc_invalid_dcc_message_format"); - return; + // Turbo DCC extension appends a "T" at the end of handshake + if ( ! (parts.size() == 7 && parts[6] == "T") ) + { + Weird("irc_invalid_dcc_message_format"); + return; + } } // Calculate IP address. @@ -663,13 +659,14 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(target.c_str())); vl->append(new StringVal(parts[1].c_str())); vl->append(new StringVal(parts[2].c_str())); vl->append(new AddrVal(htonl(raw_ip))); - vl->append(new Val(atoi(parts[4].c_str()), TYPE_INT)); - if ( parts.size() == 6 ) + vl->append(new Val(atoi(parts[4].c_str()), TYPE_COUNT)); + if ( parts.size() >= 6 ) vl->append(new Val(atoi(parts[5].c_str()), TYPE_INT)); else @@ -682,6 +679,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(target.c_str())); vl->append(new StringVal(message.c_str())); @@ -706,6 +704,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(target.c_str())); vl->append(new StringVal(message.c_str())); @@ -729,6 +728,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(target.c_str())); vl->append(new StringVal(message.c_str())); @@ -742,6 +742,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) vector parts = SplitWords(params, ' '); val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); if ( parts.size() > 0 ) vl->append(new StringVal(parts[0].c_str())); @@ -777,6 +778,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[0].c_str())); vl->append(new StringVal(parts[1].c_str())); @@ -799,6 +801,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(parts[0].c_str())); vl->append(new StringVal(parts[1].c_str())); @@ -842,6 +845,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); TableVal* list = new TableVal(irc_join_list); vector channels = SplitWords(parts[0], ','); @@ -888,6 +892,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); TableVal* list = new TableVal(irc_join_list); string empty_string = ""; @@ -965,6 +970,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(nick.c_str())); vl->append(set); vl->append(new StringVal(message.c_str())); @@ -988,6 +994,8 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(nickname.c_str())); vl->append(new StringVal(message.c_str())); @@ -1002,6 +1010,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(nick.c_str())); @@ -1027,6 +1036,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(parts[0].c_str())); vl->append(new Val(oper, TYPE_BOOL)); @@ -1055,6 +1065,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(server.c_str())); vl->append(new StringVal(users.c_str())); @@ -1065,6 +1076,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); if ( params[0] == ':' ) params = params.substr(1); @@ -1083,6 +1095,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(parts[0].c_str())); vl->append(new StringVal(parts[1].c_str())); @@ -1099,6 +1112,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(params.c_str())); @@ -1113,6 +1127,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(params.c_str())); ConnectionEvent(irc_password_message, vl); } @@ -1133,6 +1148,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(server.c_str())); vl->append(new StringVal(message.c_str())); @@ -1147,6 +1163,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(command.c_str())); vl->append(new StringVal(params.c_str())); @@ -1161,6 +1178,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) { val_list* vl = new val_list; vl->append(BuildConnVal()); + vl->append(new Val(orig, TYPE_BOOL)); vl->append(new StringVal(prefix.c_str())); vl->append(new StringVal(command.c_str())); vl->append(new StringVal(params.c_str())); diff --git a/src/event.bif b/src/event.bif index 7ec0d404ca..c3c11b6a7e 100644 --- a/src/event.bif +++ b/src/event.bif @@ -338,62 +338,60 @@ event pop3_login_success%(c: connection, is_orig: bool, event pop3_login_failure%(c: connection, is_orig: bool, user: string, password: string%); -event irc_client%(c: connection, prefix: string, data: string%); -event irc_server%(c: connection, prefix: string, data: string%); -event irc_request%(c: connection, prefix: string, +event irc_request%(c: connection, is_orig: bool, prefix: string, command: string, arguments: string%); -event irc_reply%(c: connection, prefix: string, +event irc_reply%(c: connection, is_orig: bool, prefix: string, code: count, params: string%); -event irc_message%(c: connection, prefix: string, +event irc_message%(c: connection, is_orig: bool, prefix: string, command: string, message: string%); -event irc_enter_message%(c: connection, nick: string, real_name: string%); -event irc_quit_message%(c: connection, nick: string, message: string%); -event irc_privmsg_message%(c: connection, source: string, +event irc_quit_message%(c: connection, is_orig: bool, nick: string, message: string%); +event irc_privmsg_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); -event irc_notice_message%(c: connection, source: string, +event irc_notice_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); -event irc_squery_message%(c: connection, source: string, +event irc_squery_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); -event irc_join_message%(c: connection, info_list: irc_join_list%); -event irc_part_message%(c: connection, nick: string, +event irc_join_message%(c: connection, is_orig: bool, info_list: irc_join_list%); +event irc_part_message%(c: connection, is_orig: bool, nick: string, chans: string_set, message: string%); -event irc_nick_message%(c: connection, who: string, newnick: string%); -event irc_invalid_nick%(c: connection%); -event irc_network_info%(c: connection, users: count, +event irc_nick_message%(c: connection, is_orig: bool, who: string, newnick: string%); +event irc_invalid_nick%(c: connection, is_orig: bool%); +event irc_network_info%(c: connection, is_orig: bool, users: count, services: count, servers: count%); -event irc_server_info%(c: connection, users: count, +event irc_server_info%(c: connection, is_orig: bool, users: count, services: count, servers: count%); -event irc_channel_info%(c: connection, chans: count%); -event irc_who_line%(c: connection, target_nick: string, +event irc_channel_info%(c: connection, is_orig: bool, chans: count%); +event irc_who_line%(c: connection, is_orig: bool, target_nick: string, channel: string, user: string, host: string, server: string, nick: string, params: string, hops: count, real_name: string%); -event irc_who_message%(c: connection, mask: string, oper: bool%); -event irc_whois_message%(c: connection, server: string, users: string%); -event irc_whois_user_line%(c: connection, nick: string, +event irc_who_message%(c: connection, is_orig: bool, mask: string, oper: bool%); +event irc_whois_message%(c: connection, is_orig: bool, server: string, users: string%); +event irc_whois_user_line%(c: connection, is_orig: bool, nick: string, user: string, host: string, real_name: string%); -event irc_whois_operator_line%(c: connection, nick: string%); -event irc_whois_channel_line%(c: connection, nick: string, +event irc_whois_operator_line%(c: connection, is_orig: bool, nick: string%); +event irc_whois_channel_line%(c: connection, is_orig: bool, nick: string, chans: string_set%); -event irc_oper_message%(c: connection, user: string, password: string%); -event irc_oper_response%(c: connection, got_oper: bool%); -event irc_kick_message%(c: connection, prefix: string, +event irc_oper_message%(c: connection, is_orig: bool, user: string, password: string%); +event irc_oper_response%(c: connection, is_orig: bool, got_oper: bool%); +event irc_kick_message%(c: connection, is_orig: bool, prefix: string, chans: string, users: string, comment: string%); -event irc_error_message%(c: connection, prefix: string, message: string%); -event irc_invite_message%(c: connection, prefix: string, +event irc_error_message%(c: connection, is_orig: bool, prefix: string, message: string%); +event irc_invite_message%(c: connection, is_orig: bool, prefix: string, nickname: string, channel: string%); -event irc_mode_message%(c: connection, prefix: string, params: string%); -event irc_squit_message%(c: connection, prefix: string, +event irc_mode_message%(c: connection, is_orig: bool, prefix: string, params: string%); +event irc_squit_message%(c: connection, is_orig: bool, prefix: string, server: string, message: string%); -event irc_names_info%(c: connection, c_type: string, +event irc_names_info%(c: connection, is_orig: bool, c_type: string, channel: string, users: string_set%); -event irc_dcc_message%(c: connection, prefix: string, target: string, +event irc_dcc_message%(c: connection, is_orig: bool, + prefix: string, target: string, dcc_type: string, argument: string, address: addr, dest_port: count, size: count%); -event irc_global_users%(c: connection, prefix: string, msg: string%); -event irc_user_message%(c: connection, user: string, host: string, server: string, real_name: string%); -event irc_channel_topic%(c: connection, channel: string, topic: string%); -event irc_password_message%(c: connection, password: string%); +event irc_global_users%(c: connection, is_orig: bool, prefix: string, msg: string%); +event irc_user_message%(c: connection, is_orig: bool, user: string, host: string, server: string, real_name: string%); +event irc_channel_topic%(c: connection, is_orig: bool, channel: string, topic: string%); +event irc_password_message%(c: connection, is_orig: bool, password: string%); event file_transferred%(c: connection, prefix: string, descr: string, mime_type: string%); event file_virus%(c: connection, virname: string%);