# Copyright (c) 2010 Flowerfire, Inc. All Rights Reserved. kerio_mailserver = { plugin_version = "2.2.1" info.1.manufacturer = "Kerio" info.1.device = "Mailserver" info.1.version.1 = "6.4" info.1.version.2 = "6.5" # 2007-09-11 - 1.0 - KBB - added version number and changed file name from beta_kerio_mailserver.cfg # 2008-06-03 - 2.0 - GMF - Enhanced to support new format (6.5?) with queue_id and multiple # recipient status lines, # and to track different status code in different numerical fields. # 2008-06-03 - 2.1 - GMF - Added support for security.log # 2008-06-03 - 2.2 - GMF - Added support for spam.log # 2008-06-11 - 2.2.1 - KBB - Fixed bug where non-matching lines cause error because v.remainder not set. # The name of the log format log.format.format_label = "Kerio Mailserver Mail Log Format" log.miscellaneous.log_data_type = "mail_server" log.miscellaneous.log_format_type = "mail_server" # The log is in this format if there is a match this regular expression log.format.autodetect_expression = ` matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] SMTP: From: ") or # [01/May/2008 00:08:53] Sent: Queue-ID: 48196c85-00005b1e, Recipient: , Result: delivered, Status: 2.0.0 matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] (Sent|Recv): Queue-ID: ([0-9a-f-]+), Service: SMTP, From: ") or # from security.log # [14/Apr/2008 00:38:27] Failed POP3 login from 12.34.56.78 # [14/Apr/2008 00:38:32] Failed IMAP login from 12.34.56.78, authentication method CRAM-MD5 # [14/Apr/2008 00:38:41] IP address 12.34.56.78 found in DNS blacklist SpamCop, mail from to # [14/Apr/2008 00:38:41] Attempt to deliver to unknown recipient , from , IP address 12.34.56.78 # [14/Apr/2008 00:52:39] SPF check failed: The IP address '12.34.56.78' is not in permitted set for sender 'someone@somewhere.com' (FAIL) matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] Failed (POP3|IMAP) login from ") or matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] IP address ([0-9.]+) found in DNS blacklist") or matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] Attempt to deliver to unknown recipient") or matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] SPF check failed: The IP address") or # from spam.log # [14/Apr/2008 00:04:30] Message rejected as spam with score: 10.00, threshold 2.30, From: spammer@somewhere.com, To: victim@here.com, Sender IP: 12.34.56.78, Subject: I am a bad spammer, Message size: 1973 matches_regular_expression(volatile.log_data_line, "^\\[[0-9][0-9]/[A-Z][a-z][a-z]/[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\] Message (detected|rejected) as spam") or # Placeholder in or chain false ` log.format.autodetect_lines = "5" log.filter_initialization = ` v.date = ''; v.time = ''; ` log.format.parse_only_with_filters = true log.parsing_filters.parse = ` if (matches_regular_expression(current_log_line(), "^\\[([^ ]+) ([0-9:]+)\\] (.*)$")) then ( v.date = $1; v.time = $2; v.remainder = $3; # Extract the key, if any v.key = ''; if (matches_regular_expression(v.remainder, "^(Sent|Recv): Queue-ID: ([0-9a-f-]+), (.*)$")) then ( v.key = $2; v.remainder = $3; set_collected_field(v.key, 'queue_id', v.key); ); set_collected_field(v.key, 'date', v.date); set_collected_field(v.key, 'time', v.time); # Handle From lines if (matches_regular_expression(v.remainder, "^(SMTP:|Service: SMTP,) From: <([^>]*)>, To: <([^>]*)>, Size: ([0-9]+), Sender-Host: (.*)$")) then ( set_collected_field(v.key, 'sender', $2); set_collected_field(v.key, 'recipient', $3); v.size = $4; set_collected_field(v.key, 'size', v.size); set_collected_field(v.key, 'sender_host', $5); set_collected_field(v.key, 'type', 'SMTP'); # If there is no key, this is all we'll get of this message; accept it now, and assume it was delivered if (v.key eq '') then ( set_collected_field(v.key, 'messages_queued', 1); set_collected_field(v.key, 'bytes_queued', v.size); set_collected_field(v.key, 'messages_delivered', 1); set_collected_field(v.key, 'bytes_delivered', v.size); accept_collected_entry(v.key, false); ); # If there was a key, accept this as a queued message, but carry over for Recipient lines else ( set_collected_field(v.key, 'messages_queued', 1); set_collected_field(v.key, 'bytes_queued', v.size); accept_collected_entry(v.key, true); ); ); # if SMTP From # Handle Recipient lines else if (matches_regular_expression(v.remainder, "^Recipient: <([^>]+)>, Result: ([^,]+), Status: (.*)$")) then ( set_collected_field(v.key, 'recipient', $1); v.result = $2; set_collected_field(v.key, 'result', v.result); set_collected_field(v.key, 'status', $3); set_collected_field(v.key, 'type', 'SMTP'); v.size = get_collected_field(v.key, 'size'); # Reset queued fields; this line is not showing anything being queued. set_collected_field(v.key, 'messages_queued', 0); set_collected_field(v.key, 'bytes_queued', 0); set_collected_field(v.key, 'messages_delivered', 0); set_collected_field(v.key, 'bytes_delivered', 0); set_collected_field(v.key, 'messages_relayed', 0); set_collected_field(v.key, 'bytes_relayed', 0); set_collected_field(v.key, 'messages_failed', 0); set_collected_field(v.key, 'bytes_failed', 0); set_collected_field(v.key, 'messages_delayed', 0); set_collected_field(v.key, 'bytes_delayed', 0); # Set numerical fields according to what happened to this message. if (v.result eq 'delivered') then ( set_collected_field(v.key, 'messages_delivered', 1); set_collected_field(v.key, 'bytes_delivered', v.size); ); else if (v.result eq 'relayed') then ( set_collected_field(v.key, 'messages_relayed', 1); set_collected_field(v.key, 'bytes_relayed', v.size); ); else if (v.result eq 'failed') then ( set_collected_field(v.key, 'messages_failed', 1); set_collected_field(v.key, 'bytes_relayed', v.size); ); else if (v.result eq 'delayed') then ( set_collected_field(v.key, 'messages_delayed', 1); set_collected_field(v.key, 'bytes_relayed', v.size); ); accept_collected_entry(v.key, true); ); # if Recipient # Handle security log line: # [14/Apr/2008 00:38:27] Failed POP3 login from 12.34.56.78 # [14/Apr/2008 00:38:32] Failed IMAP login from 12.34.56.78, authentication method CRAM-MD5 else if (matches_regular_expression(v.remainder, "^(Failed )([^ ]+)( login) from ([^,]+)(.*)$")) then ( set_collected_field(v.key, 'type', 'security'); set_collected_field(v.key, 'security_events', 1); set_collected_field(v.key, 'subtype', $1 . $2 . $3); set_collected_field(v.key, 'sender_host', $4); v.remainder = $5; if (matches_regular_expression(v.remainder, '^, authentication method ([^,]+)(.*)$')) then ( set_collected_field(v.key, 'authentication_method', $1); v.remainder = $2; ); if (matches_regular_expression(v.remainder, '^, user ([^,]+)(.*)$')) then ( set_collected_field(v.key, 'user', $1); v.remainder = $2; ); accept_collected_entry(v.key, false); ); # if Failed login # [14/Apr/2008 00:38:41] IP address 12.34.56.78 found in DNS blacklist SpamCop, mail from to else if (matches_regular_expression(v.remainder, "^(IP address) ([^ ]+)( found in DNS blacklist) ([^,]+), mail from <([^>]+)> to <([^>]+)>")) then ( set_collected_field(v.key, 'type', 'security'); set_collected_field(v.key, 'security_events', 1); set_collected_field(v.key, 'subtype', $1 . $3); set_collected_field(v.key, 'sender_host', $2); set_collected_field(v.key, 'blacklist', $4); set_collected_field(v.key, 'sender', $5); set_collected_field(v.key, 'recipient', $6); accept_collected_entry(v.key, false); ); # if DNS blacklist # [14/Apr/2008 00:38:41] Attempt to deliver to unknown recipient , from , IP address 12.34.56.78 else if (matches_regular_expression(v.remainder, "^(Attempt to deliver to unknown recipient) <([^>]+)>, from <([^>]+)>, IP address (.*)$")) then ( set_collected_field(v.key, 'type', 'security'); set_collected_field(v.key, 'security_events', 1); set_collected_field(v.key, 'subtype', $1); set_collected_field(v.key, 'sender', $2); set_collected_field(v.key, 'recipient', $3); set_collected_field(v.key, 'sender_host', $4); accept_collected_entry(v.key, false); ); # Unknown recipient # [14/Apr/2008 00:52:39] SPF check failed: The IP address '12.34.56.78' is not in permitted set for sender 'someone@somewhere.com' (FAIL) else if (matches_regular_expression(v.remainder, "^(SPF check failed): The IP address '([^']+)' is not in permitted set for sender '([^']+)'")) then ( set_collected_field(v.key, 'type', 'security'); set_collected_field(v.key, 'security_events', 1); set_collected_field(v.key, 'subtype', $1); set_collected_field(v.key, 'sender_host', $2); set_collected_field(v.key, 'sender', $3); accept_collected_entry(v.key, false); ); # SPF check failed # [14/Apr/2008 00:00:03] Message from IP address 12.34.56.78, sender <#@[]> rejected: sender domain does not exist else if (matches_regular_expression(v.remainder, "^(Message )from IP address ([^ ]+), sender <([^>]+)> (rejected: .*)")) then ( set_collected_field(v.key, 'type', 'security'); set_collected_field(v.key, 'security_events', 1); set_collected_field(v.key, 'subtype', $1 . $4); set_collected_field(v.key, 'sender_host', $2); set_collected_field(v.key, 'sender', $3); accept_collected_entry(v.key, false); ); # Message rejected # [14/Apr/2008 00:04:30] Message rejected as spam with score: 10.00, threshold 2.30, From: spammer@somewhere.com, To: victim@here.com, Sender IP: 12.34.56.78, Subject: I am a bad spammer, Message size: 1973 else if (matches_regular_expression(v.remainder, "^(Message )(rejected|detected)( as spam) with score: ([^,]+), threshold ([^,]+), From: ([^,]+), To: ([^,]+), Sender IP: ([^,]+), Subject: (.*), Message size: (.*)$")) then ( set_collected_field(v.key, 'type', $1 . $2 . $3); set_collected_field(v.key, 'messages_spam_filtered', 1); set_collected_field(v.key, 'spam_score', $4); set_collected_field(v.key, 'spam_threshold', $5); set_collected_field(v.key, 'sender', $6); set_collected_field(v.key, 'recipient', $7); set_collected_field(v.key, 'sender_host', $8); set_collected_field(v.key, 'spam_subject', $9); set_collected_field(v.key, 'bytes_spam_filtered', $10); accept_collected_entry(v.key, false); ); # Message rejected ); ` # Log fields log.fields = { date = "" time = "" type = "" subtype = "" sender = { type = "hierarchical" hierarchy_dividers = "@" left_to_right = false leading_divider = false } recipient = { type = "hierarchical" hierarchy_dividers = "@" left_to_right = false leading_divider = false } sender_host.type = "host" authentication_method = "" user = "" blacklist = "" spam_score = "" spam_threshold = "" spam_subject = "" queue_id = "" messages_queued = "" messages_delivered = "" messages_delayed = "" messages_relayed = "" messages_failed = "" messages_spam_filtered = "" bytes_queued = "" bytes_delivered = "" bytes_delayed = "" bytes_relayed = "" bytes_failed = "" bytes_spam_filtered = "" security_events = "" } # log.fields # Database fields database.fields = { date_time = "" day_of_week = "" hour_of_day = "" type = "" subtype = "" sender = "" recipient = "" sender_host = "" location = "" authentication_method = "" user = "" blacklist = "" spam_score = "" spam_threshold = "" spam_subject = "" queue_id = "" } # database.fields database.numerical_fields = { messages_queued = { default = true } messages_delivered = { default = true } messages_delayed = { default = true } messages_relayed = { default = true } messages_failed = { default = true } messages_spam_filtered = { default = true } bytes_queued = { type = "float" display_format_type = "bandwidth" } bytes_delivered = { type = "float" display_format_type = "bandwidth" } bytes_delayed = { type = "float" display_format_type = "bandwidth" } bytes_relayed = { type = "float" display_format_type = "bandwidth" } bytes_failed = { type = "float" display_format_type = "bandwidth" } bytes_spam_filtered = { type = "float" display_format_type = "bandwidth" } security_events = "" } # database.numerical_fields create_profile_wizard_options = { # How the reports should be grouped in the report menu report_groups = { date_time_group = "" } # report_groups } # create_profile_wizard_options } # kerio_mailserver