# Copyright (c) 2014 Flowerfire, Inc. All Rights Reserved. exchange_server_w3c = { info.1.manufacturer = "Microsoft" info.1.device = "Exchange Server (W3C)" info.1.version.1 = "2013" plugin_version = "1.1" # 2014-06-03 - 1.0 - GMF - Initial Implementation # 2014-06-10 - 1.1 - GMF - Added mail_server_reports snapon, and messages field # The name of the log format log.format.format_label = "Microsoft Exchange Server (W3C) Log Format" log.miscellaneous.log_data_type = "mail_server" log.miscellaneous.log_format_type = "mail_server" # The log is in this format if any of the first ten lines match this regular expression log.format.autodetect_regular_expression = "^#Software: Microsoft Exchange Server" log.format.treat_apostrophes_as_quotes = false log.format.ignore_format_lines = "true" # This handles #Fields lines, and creates log and database fields from them log.filter_preprocessor = ` if (matches_regular_expression(current_log_line(), '^#Fields: +([^ ].*)$')) then ( string fields = $1; string fieldname; v.logfieldindex = 1; string numerical_fields = "profiles." . internal.profile_name . ".database.numerical_fields"; # Send this line to all parsing servers distribute_format_line(current_log_line()); # Reset all log fields to 0/0 so none carry over from the previous format line definition node log_fields = "profiles"{internal.profile_name}{"log"}{"fields"}; node log_field; foreach log_field log_fields ( @log_field{"index"} = 0; @log_field{"subindex"} = 0; ); # This subroutine creates a database field subroutine(create_database_field(string fieldname, int top, int bottom), ( #echo("create_database_field: " . fieldname); # debug debug_message("create_database_field(" . fieldname . ")\n"); string databasefieldpath = "profiles." . internal.profile_name . ".database.fields." . fieldname; (databasefieldpath . "") = ""; node databasefield = databasefieldpath; if (top ne 0) then set_subnode_value(databasefield, "suppress_top", top); if (bottom ne 0) then set_subnode_value(databasefield, "suppress_bottom", bottom); databasefield; )); subroutine(create_log_field(string fieldname, string type, bool withindex), ( debug_message("create_log_field(" . fieldname . "; type=" . type . ")\n"); # echo("create_log_field(" . fieldname . "; type=" . type . "; type=" . type . ")"); string logfieldpath = "profiles." . internal.profile_name . ".log.fields." . fieldname; (logfieldpath . "") = ""; node logfield = logfieldpath; if (withindex) then ( set_subnode_value(logfield, "index", v.logfieldindex); v.logfieldindex++; ); set_subnode_value(logfield, "subindex", 0); if (type ne '') then set_subnode_value(logfield, "type", type); logfield; )); log.format.field_separator = ","; fields = replace_all(fields, 'date-time', 'unnormalized-date-time'); # Extract the fields on at a time while (matches_regular_expression(fields, '^([^,]+),(.*)$') or matches_regular_expression(fields, '^([^,]+)$')) ( string unconverted_fieldname = $1; fields = $2; # Clean up the field name fieldname = ''; for (int i = 0; i < length(unconverted_fieldname); i++) ( string c = lowercase(substr(unconverted_fieldname, i, 1)); if (!matches_regular_expression(c, '^[a-z0-9]$')) then c = '_'; fieldname .= c; ); while (matches_regular_expression(fieldname, '^(.*)_$')) fieldname = $1; # Get the log field type string log_field_type = ''; if (fieldname eq 'cs_referrer') then ( fieldname = 'cs_referer'; ); if (fieldname eq 'cs_uri') then ( fieldname = 'cs_uri_stem'; ); # 2013-12-23 - GMF - Don't make cs_referrer type "referrer" anymore; we now do all referrer derivation in snapons, and this will create duplicate fields. # if (fieldname eq 'cs_referer') then ( # log_field_type = 'url'; # ); # 2013-12-23 - GMF - Don't make cs_uri_stem type "page" anymore; we now have a snapon computing screen dimensions, and if we make this type page, it will override cs_uri_stem with "(screen info)" and then screen info from the snapon won't be computed. # else if (fieldname eq 'cs_uri_stem') then ( # log_field_type = 'page'; # ); # 2013-12-23 - GMF - Don't make cs_referrer type "agent" anymore; we now do all agent derivation in snapons, and this will create duplicate fields. # else if (fieldname eq 'cs_user_agent') then ( # log_field_type = 'agent'; # ); # 2013-12-23 - GMF - Don't make c_ip type "host" anymore; we now do all agent derivation in snapons, and this will create duplicate fields. # else if (fieldname eq 'c_ip') then ( # log_field_type = 'host'; # ); # Create the log field # 2013-05-15 - GMF - We need to create these sc_bytes and cs_bytes log fields here, because otherwise web_server_package won't create the database fields. Why were they excluded? Maybe when this was copied from another plug-in which computes them from another field? # if ((fieldname ne "sc_bytes") and (fieldname ne "cs_bytes")) then # if (fieldname ne "date_time") then create_log_field(fieldname, log_field_type, true); # If we're creating a profile, create the database fields too. if (node_exists("volatile.creating_profile")) then ( # Handle localtime by creating date_time and derived database fields if (fieldname eq "unnormalized_date_time") then ( create_log_field('date', '', false); create_log_field('time', '', false); create_database_field('date_time', 0, 0); create_database_field('day_of_week', 0, 0); create_database_field('hour_of_day', 0, 0); ); # if localtime # Don't track these fields in the database else if ((fieldname eq "sc_bytes") or (fieldname eq "cs_bytes") or (fieldname eq 'cs_uri_query') or (fieldname eq 'cs_cookie')) then ( ); # Handle date by creating date_time and derived database fields else if (fieldname eq "date") then ( create_log_field('localtime', '', false); # placeholder - 7/Nov/2006 - KBB create_database_field('date_time', 0, 0); create_database_field('day_of_week', 0, 0); create_database_field('hour_of_day', 0, 0); ); # if date else if (fieldname eq "time") then ( create_database_field('date_time', 0, 0); create_database_field('day_of_week', 0, 0); create_database_field('hour_of_day', 0, 0); ); # if time # Create derived fields for agent else if (fieldname eq "cs_user_agent") then ( # create_database_field('operating_system', 0, 0); # create_database_field('web_browser', 0, 0); # create_database_field('spider', 0, 0); ); # Create database field cs_ip and derived field for client IP else if (fieldname eq "c_ip") then ( create_database_field('c_ip', 0, 0); # create_database_field('location', 0, 0); ); # Create database field cs_referer and derived fields for referrer else if (fieldname eq "cs_referer") then ( create_database_field('cs_referer', 1, 9); # create_database_field('search_engine', 0, 0); # create_database_field('search_phrase', 0, 0); ); # Create derived file type field else if (fieldname eq "cs_uri_stem") then ( create_database_field('cs_uri_stem', 0, 9); # 2013-12-23 - GMF - Don't file_type anymore; this is done with a snapon now # create_database_field('file_type', 0, 0); ); # Don't add a database field for numerical fields else if (subnode_exists(numerical_fields, fieldname)) then ( debug_message("Not adding numerical field: " . fieldname . "\n"); ); # Create a normal database field else create_database_field(fieldname, 0, 0); ); # if creating profile ); # while another field # Don't parse the #Fields line as a data line 'reject'; ); # if #Fields # Don't parse any other # lines as data lines else if (starts_with(current_log_line(), '#')) then ( 'reject'; ); ` # Log fields log.fields = { # date_time = "" } # log.fields # Database fields database.fields = { } # database.fields log.parsing_filters.parse = ` if (matches_regular_expression(unnormalized_date_time, '^([0-9-]+)T([0-9:]+)[.]')) then ( date = normalize_date($1, 'auto'); time = $2; ); ` # Log Filters log.filters = { mark_entry = { label = '$lang_admin.log_filters.mark_entry_label' comment = '$lang_admin.log_filters.mark_entry_comment' value = 'events = 1;' } # mark_entry } # log.filters database.numerical_fields = { events = { default = true requires_log_field = false entries_field = true } # events total_bytes = { type = "int" integer_bits = 64 display_format_type = "bandwidth" } # total_bytes # unique_client_ips = { # log_field = "client_ip" # type = "unique" # } # unique_client_ips # unique_message_ids = { # default = true # log_field = "msgid" # type = "unique" # } # unique_message_ids recipient_count = "" messages = { type = "unique" log_field = "message_id" } } # database.numerical_fields create_profile_wizard_options = { # How the reports should be grouped in the report menu report_groups = { date_time_group = "" sender_group = { sender_address = true sender_domain = true } recipient_group = { recipient_address = true recipient_domain = true recipient_report_status = true number_recipients = true alias = true } server_group = { server_ip = true server_hostname = true service_version = true } client_group = { client_ip = true client_hostname = true } message_group = { message_subject = true msgid = true linked_msg_id = true } other_group = { partner_name = true priority = true encryption = true event_id = true origination_time = true } } # report_groups snapons = { # Attach a mail_server_reports snapon mail_server_reports = { snapon = "mail_server_reports" name = "mail_server_reports" label = "$lang_admin.snapons.mail_server_reports.label" parameters = { sender_field.parameter_value = "sender_address" recipient_field.parameter_value = "recipient_address" messages_processed_field.parameter_value = "messages" have_messages_delivered_field.parameter_value = false # messages_delivered_field.parameter_value = "messages_delivered" } # parameters } # mail_server_reports # Add the standard reports add_standard_reports = { name = "add_standard_reports" label = "add_standard_reports" snapon = "add_standard_reports" } # add_standard_reports } # snapons } # create_profile_wizard_options } # exchange_server_w3c