mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
192 lines
5.3 KiB
Text
192 lines
5.3 KiB
Text
# $Id: smtp-relay.bro 5911 2008-07-03 22:59:01Z vern $
|
|
#
|
|
# Tracks email relaying.
|
|
|
|
@load smtp
|
|
@load mime
|
|
|
|
module SMTP;
|
|
|
|
redef process_smtp_relay = T;
|
|
|
|
export {
|
|
const relay_log = open_log_file("relay") &redef;
|
|
}
|
|
|
|
global print_smtp_relay: function(t: table[count] of smtp_session_info,
|
|
idx: count): interval;
|
|
|
|
global smtp_relay_table: table[count] of smtp_session_info
|
|
&write_expire = 5 min &expire_func = print_smtp_relay;
|
|
|
|
global smtp_session_by_recipient: table[string] of smtp_session_info
|
|
&write_expire = 5 min;
|
|
global smtp_session_by_message_id: table[string] of smtp_session_info
|
|
&write_expire = 5 min;
|
|
global smtp_session_by_content_hash: table[string] of smtp_session_info
|
|
&write_expire = 5 min;
|
|
|
|
|
|
function add_to_smtp_relay_table(session: smtp_session_info)
|
|
{
|
|
if ( session$id !in smtp_relay_table )
|
|
smtp_relay_table[session$id] = session;
|
|
}
|
|
|
|
function check_relay_1(session: smtp_session_info, rcpt: string)
|
|
{
|
|
if ( session$external_orig && rcpt != local_mail_addr )
|
|
{
|
|
smtp_message(session,
|
|
fmt("relaying(1) message (from %s, to %s) to address %s",
|
|
session$connection_id$orig_h,
|
|
session$connection_id$resp_h,
|
|
rcpt));
|
|
|
|
if ( session$relay_1_rcpt != "" )
|
|
session$relay_1_rcpt = cat(session$relay_1_rcpt, ",");
|
|
|
|
session$relay_1_rcpt = cat(session$relay_1_rcpt, rcpt);
|
|
add_to_smtp_relay_table(session);
|
|
}
|
|
}
|
|
|
|
function check_relay_2(session: smtp_session_info, rcpt: string)
|
|
{
|
|
if ( rcpt in smtp_session_by_recipient )
|
|
{
|
|
local prev_session = smtp_session_by_recipient[rcpt];
|
|
|
|
# Should only check the first condition only (external
|
|
# followed by internal) but let's include the second one
|
|
# for testing purposes for now.
|
|
if ( (prev_session$external_orig && ! session$external_orig) ||
|
|
(! prev_session$external_orig && session$external_orig) )
|
|
{
|
|
smtp_message(session,
|
|
fmt("relaying(2) message (seen during #%d) to address %s (%s -> %s, %s -> %s)",
|
|
prev_session$id, rcpt,
|
|
prev_session$connection_id$orig_h,
|
|
prev_session$connection_id$resp_h,
|
|
session$connection_id$orig_h,
|
|
session$connection_id$resp_h));
|
|
|
|
session$relay_2_from = prev_session$id;
|
|
++prev_session$relay_2_to;
|
|
|
|
add_to_smtp_relay_table(session);
|
|
add_to_smtp_relay_table(prev_session);
|
|
}
|
|
}
|
|
|
|
smtp_session_by_recipient[rcpt] = session;
|
|
}
|
|
|
|
function check_relay_3(session: MIME::mime_session_info, msg_id: string)
|
|
{
|
|
local smtp_session = session$smtp_session;
|
|
|
|
if ( msg_id in smtp_session_by_message_id )
|
|
{
|
|
local prev_smtp_session = smtp_session_by_message_id[msg_id];
|
|
|
|
smtp_message(smtp_session,
|
|
fmt("relaying(3) message (seen during #%d) with id %s (%s -> %s, %s -> %s)",
|
|
prev_smtp_session$id, msg_id,
|
|
prev_smtp_session$connection_id$orig_h,
|
|
prev_smtp_session$connection_id$resp_h,
|
|
smtp_session$connection_id$orig_h,
|
|
smtp_session$connection_id$resp_h));
|
|
|
|
smtp_session$relay_3_from = prev_smtp_session$id;
|
|
++prev_smtp_session$relay_3_to;
|
|
|
|
add_to_smtp_relay_table(smtp_session);
|
|
add_to_smtp_relay_table(prev_smtp_session);
|
|
}
|
|
else
|
|
smtp_session_by_message_id[msg_id] = smtp_session;
|
|
}
|
|
|
|
function check_relay_4(session: MIME::mime_session_info, content_hash: string)
|
|
{
|
|
local smtp_session = session$smtp_session;
|
|
smtp_session$content_hash = content_hash;
|
|
|
|
if ( content_hash in smtp_session_by_content_hash )
|
|
{
|
|
local prev_smtp_session = smtp_session_by_content_hash[content_hash];
|
|
smtp_message(smtp_session,
|
|
fmt("relaying(4) message (seen during #%d) with hash %s (%s -> %s, %s -> %s)",
|
|
prev_smtp_session$id,
|
|
string_to_ascii_hex(content_hash),
|
|
prev_smtp_session$connection_id$orig_h,
|
|
prev_smtp_session$connection_id$resp_h,
|
|
smtp_session$connection_id$orig_h,
|
|
smtp_session$connection_id$resp_h));
|
|
|
|
smtp_session$relay_4_from = prev_smtp_session$id;
|
|
++prev_smtp_session$relay_4_to;
|
|
|
|
add_to_smtp_relay_table(smtp_session);
|
|
add_to_smtp_relay_table(prev_smtp_session);
|
|
}
|
|
else
|
|
smtp_session_by_content_hash[content_hash] = smtp_session;
|
|
}
|
|
|
|
# event mime_all_data(c: connection, length: count, data: string)
|
|
# {
|
|
# local session = get_mime_session(c, T);
|
|
# session$content_hash = md5_hash(data);
|
|
# if ( process_smtp_relay )
|
|
# check_relay_4(session, session$content_hash);
|
|
# # mime_log_msg(session, "all data", fmt("%s", data));
|
|
# }
|
|
|
|
event mime_content_hash(c: connection, content_len: count, hash_value: string)
|
|
{
|
|
local session = MIME::get_session(c, T);
|
|
session$content_hash = hash_value;
|
|
if ( process_smtp_relay && content_len > 0 )
|
|
check_relay_4(session, session$content_hash);
|
|
}
|
|
|
|
function relay_flow(from: count, to: count): string
|
|
{
|
|
if ( from > 0 )
|
|
return fmt("<#%d", from);
|
|
|
|
if ( to > 0 )
|
|
return fmt(">%d", to);
|
|
|
|
return "-";
|
|
}
|
|
|
|
function print_smtp_relay(t: table[count] of smtp_session_info,
|
|
idx: count): interval
|
|
{
|
|
local session = t[idx];
|
|
|
|
print relay_log, fmt("#%d: %s",
|
|
session$id,
|
|
directed_id_string(session$connection_id, T));
|
|
|
|
print relay_log, fmt("#%d: RCPT: <%s>, Subject: %s",
|
|
session$id,
|
|
session$recipients, session$subject);
|
|
|
|
print relay_log, fmt("#%d: detected: [%s %s %s %s] %s",
|
|
session$id,
|
|
session$relay_1_rcpt == "" ? "-" : "1",
|
|
relay_flow(session$relay_2_from, session$relay_2_to),
|
|
relay_flow(session$relay_3_from, session$relay_3_to),
|
|
relay_flow(session$relay_4_from, session$relay_4_to),
|
|
session$content_gap ? "(content gap)" : "");
|
|
|
|
print relay_log, fmt("#%d: relay 1: <%s>",
|
|
session$id,
|
|
session$relay_1_rcpt);
|
|
|
|
return 0 sec;
|
|
}
|