$! AUDIT_LOG.TEMPLATE -- This is a template file -- rename to AUDIT_LOG.COM $! $! Security Audit Journal/Archive Control & Analysis $! for VMS V5.2 and later. $! $! ** See the end of this file for documentation ** $! $! Site Specific Parameters Are Next $!==================================================================== $! SITE SPECIFIC PARAMETER SECTION $!==================================================================== $! $! This user receives all of the security audit analysis outputs $! $ security_manager = "Your_Favorite_Martian_Here" $! $! This next list of user(s) receives only the breakin detection analysis $! results. This would include any operations/support staff who may $! need to be aware of attempted breakins in case assistance with passwords $! is requested. $! $! If you don't want it to go to anyone other than the security manager, $! then set this one to null $! $ breakin_notice_recipients = "list,of,others" ! "OPERATIONS" $! $! Your site name should go here. You can override this one with $! a logical name definition -- look at the sample SYSECURITY.COM for $! a definition example. $! $ site_name_default = "YourSiteNameHere" $ $! $! Where the sub-procedures live (copies came with the distribution) $! $ cluster_do = "@UTL:CLUSTER_DO" ! execute a command on all the cpus in the cluster $ getnode = "@UTL:GETNODE" ! multi-method node name determination $! $! List of events to be given in brief form on a daily basis. $! $ event_brief_list = "SYSUAF,NETUAF,LOGFAIL,BREAKIN" $! $! List of events to report as breakins or other serious events. $! $ event_full_list = "BREAKIN" $! $! End of site specific parameter section $!================================================================== $ vfl = f$ver(0.or.f$trnlnm("debug$audit").or.f$trnlnm("debug$dcl")) $ set noon $! to find out where this procedure lives and the directory it's in... $ who_am_i = f$element(0,";",f$environment("procedure")) ! latest version $ who_am_i_exactly = f$environment("procedure") ! this very procedure $ where_am_i = f$parse("a.b;0",who_am_i,,,"syntax_only")-"A.B;0" $ vms_version = f$getsyi("version") $ if f$loc(".",vms_version).lt.f$len(vms_version) $ then $ if (vms_version-".").lts."V52" $ then $ write sys$output who_am_i,"-F-VERMISMATCH,",- " this procedure requires VMS V5.2 or later" $ exit %X80010004 $ endif $ endif $ invocation = p1 $ analyze_flag = p2 $ null = "" $! $! List of different choices for ARCHIVE_TYPE logical name. $ archive_choices = "A,B,C" $! $ req_priv = "SECURITY,SYSNAM,SYSPRV,BYPASS" $ lnm_table = "lnm$group_000001" $! $! Determine if a SITE name has been supplied $! $ site_name = f$trnlnm("SITE_NAME","LNM$SYSTEM","EXECUTIVE") $ if site_name.eqs.null then $ site_name = site_name_default $! $! Elevate privileges $! $ save_privs = f$setprv(req_priv) $! $! The archive type should be defined in SYS$MANAGER:SYSECURITY.COM or $! SYS$STARTUP:LOC$SECURITY.COM. Defaults to "A" $! $ archive_type = f$trnlnm("audit_archive_type",lnm_table,"executive") $ if archive_type.eqs.null then $ archive_type = "A" $ archive_type = f$edit(f$ext(0,1,archive_type),"upcase") $ security_audit_directory = f$parse("A.B;",- f$trnlnm("audit_server","lnm$system","executive"))-"A.B;" $ audit_journal_directory = f$parse("[journal]",security_audit_directory)-".;" $ audit_archive_directory = f$parse("[archive]",security_audit_directory)-".;" $ audit_work_directory = f$parse("[work]",security_audit_directory)-".;" $ tmp_file = audit_journal_directory+"security.tmp" $ if f$type(my_node).eqs.null then $ getnode my_node $ defgroup = "define/table="+lnm_table+"/executive_mode/name_attrib=no_alias" $! $! Compute the new audit and archive file names $! $ date = f$cvtime(null,,"date") $ new_audit_file = f$parse(date+"_"+site_name,audit_journal_directory) $ new_audit_journal = f$parse(".audit$journal",new_audit_file) $ month = f$cvtime(null,,"year")+"-"+f$cvtime(null,,"month") $ if archive_type .eqs."B" $ then ! archive_type=B $ new_audit_archive = f$parse(month+"_"+my_node+".AUDIT$archive",- audit_archive_directory) $ else $ if archive_type .eqs."C" .or. archive_type .eqs."A" $ then ! archive_type = C or A $ new_audit_archive = f$parse(month+"_"+site_name+".AUDIT$archive",- audit_archive_directory) $ endif ! archive_type = C or A $ endif ! archive_type = B $ old_audit_journal = - f$search(f$trnlnm("audit_journal",lnm_table,"executive")) $ old_audit_archive = - f$trnlnm("audit_archive",lnm_table,"executive") $ OLD_archive_name = f$PARSE(old_audit_archive,,,"name") $ new_archive_name = f$parse(new_audit_archive,,,"name") $ OLD_journal_name = f$PARSE(old_audit_journal,,,"name") $ new_journal_name = f$parse(new_audit_journal,,,"name") $ if f$ver() then $ show sym/local/all $! $! Is it time to setup a new journal file (new day) ? $! $ if f$parse(";",old_audit_journal).nes.f$parse(";",new_audit_journal) $ then ! need a new journal $ defgroup audit_journal 'new_audit_journal' $ if invocation.nes."STARTUP" $ then ! It isn't startup $ cluster_do "''defgroup' audit_journal ''new_audit_journal'" $ tvfl = f$ver(1) $! Use method 1 if uic group is same as 1 $ if f$getjpi(null,"GRP").eq.1 $ then ! UIC GRP = 1 $! method 1 $ cluster_do "set audit/journal/destination=audit_journal:" $! "show device/file/nosys audit_journal:" ! debug code $! $ else ! the user is in a different UIC group so use actual name $! method 2 $ cluster_do "set audit/journal/destination=''new_audit_journal'" $! "show device/file/nosys audit_journal:" ! debug code $ endif ! uic group $ directory/date=all 'f$parse(";*",new_audit_journal)' $ set audit/server=new_log $! cluster_do "sho dev/file/nosys audit_server:" ! debug code $ directory/date=all 'f$parse(";*",new_audit_journal)' $ tmp = f$ver(tvfl) $ if f$ver() then $ show audit/all $! $! Do we need to do an analysis of the old file(s)? $! $ else ! This is STARTUP time $ set audit/journal/dest=audit_journal: $ endif ! not startup $ else ! no new journal $ if invocation.eqs."STARTUP" ! startup in progress $ then $ set audit/journal/dest=audit_journal: $ endif $ endif ! new journal needed $ if analyze_flag $ then ! analyze flag $ if f$parse(";",old_audit_journal).eqs.f$parse(";",new_audit_journal) then - $ old_audit_journal = null $ old_date = "yesterday" $ old_suffix = "_"+site_name+".audit$journal" $ old_journal_loop: $ old_file = - f$parse(f$cvtime(old_date,,"date")+old_suffix,audit_journal_directory) $ previous_journal = f$search(old_file) $ if previous_journal.eqs.null $ then $ old_date = f$cvtime(old_date+"-1-0:","absolute","date") $ if f$cvtime(old_date).gts.f$cvtime("today-31-0:") then $ goto old_journal_loop $ endif $ old_audit_journal = f$parse(";*",old_audit_journal,previous_journal) $ if f$ver() then $ show sym old_audit_journal $ analyze/audit/event=('event_brief_list')/output='tmp_file' 'old_audit_journal' $ analyze/audit/event=('event_full_list')/output='tmp_file'/full 'old_audit_journal' $ if f$search(tmp_file+";").nes.null $ then ! tmp_file created $! Analyze/audit always produces a file even if it's empty, so check here $ if (breakin_notice_recipients.nes.null) .and. - (f$file_attribute(tmp_file,"eof").ne.0) then - $ mail/subj="Security Alarms Detected" 'tmp_file' - 'breakin_notice_recipients' $ if f$search(tmp_file+";-1").nes.null then - $ append 'tmp_file';-1 'tmp_file';/log $! Analyze/audit always produces a file even if it's empty, so check here $ if f$file_attribute(tmp_file,"eof").ne.0 then - $ mail 'tmp_file' 'security_manager'/subj="Security Alarms Detected" $ delete 'tmp_file';* $ endif ! tmp_file created $ endif ! analyze flag $! $! Is it time for a new archive file to be set up ? $! $ if old_archive_name.nes.new_archive_name .or. - f$parse(";",old_audit_archive).nes.f$parse(";",new_audit_archive) $ then ! new archive is needed $ defgroup audit_archive 'new_audit_archive' $! $! RLB 4-Jan-1990 $! $! Due to strangeness of the behavior of V5.2 audit archive I have $! decided for this implementation to use mode B. $! This is not the slickest way to do it since it involves having a $! separate audit server database file for each node in the cluster. $! $! The reason for this is that the archive file cannot be shared by different $! cpus in the cluster, yet the SET AUDIT/ARCHIVE/DEST=file command does the $! following: $! $! 1. Causes the audit server on the local node to change its archive file $! to the new file name. $! $! 2. Updates the AUDIT_SERVER.DAT file so that subsequent attempts to $! open the archive file on other nodes in the cluster fail. The net $! effect of this is that the audit servers die when they experience $! the open failure. $! $! The workarounds are: $! $! A. Don't have continuous archiving. Use a weekend or month-end $! analyze/audit/output=binary to generate an archival file. $! $! B. Have separate AUDIT_SERVER.DAT and archive files for each node. $! This may not be any problem because of the use of SYSMAN. $! The best strategy is to name the database to be $! _audit_server.dat $! $! $ if archive_type.eqs."B" $ then ! archive_type = B $ if invocation.nes."STARTUP" $ then ! not startup $ cluster_do - "if f$type(my_node).eqs."""" then $ ''getnode' my_node" - "naa=""''audit_archive_directory'''month'_""+my_node+"".audit$archive""" - "define/tab=''lnm_table'/exec audit_archive 'naa'" - "set audit/arch=ALL/dest='naa'" $ else ! startup $ set audit/archive/dest=audit_archive: $ endif $ else $ if archive_type.eqs."C" $! $! Use type C only when cluster-wide sharing of the archive file is $! working properly. $! $ then ! archive_type = C $ set audit/archive/destination='new_audit_archive' $ endif ! archive type = C $ endif ! archive type = B $! $! Workaround A $! If it is a new month, then archive all of the last month's records into $! an archive file. $! $! Workaround B $! If it is a new month, then combine all of the archives for the last month $! from each node into a combined cluster archive file. This option also $! requires having a separate AUDIT_SERVER.DAT for each node. $! $! Then prepare a summary from the archive file and send $! it to the security manager $! $ if analyze_flag $ then ! analyze the archive $! prepare the file names $ @utl:cvtime lastmonth last_month $ @utl:cvtime thismonth this_month $ month_prefix = f$cvtime(last_month,,"year")+"-"+- f$cvtime(last_month,,"month") $ month_file_prefix = audit_journal_directory+month_prefix $ summary_file = audit_work_directory+month_prefix+"_"+site_name+".audit$summary" $! $! combine the files into 1 if not using type C $! $ site_audit_archive = old_audit_archive $ if archive_type.eqs."A" $ then ! archive_type = A $ analyze/audit 'audit_journal_directory''month_prefix'-%%_*.audit$journal;*- /since='last_month'/before='this_month' - /binary/output='site_audit_archive' $ else $ if archive_type.eqs."B" $ then ! archive_type = B $ month_prefix = - f$cvtime(last_month,,"year")+"-"+f$cvtime(last_month,,"month") $ site_audit_archive = audit_archive_directory+ - month_prefix+"_"+site_name+".audit$archive" $ analyze/audit - 'audit_archive_directory''month_prefix'_*.audit$archive;*- /binary/output='site_audit_archive' $ endif ! type = B $ endif ! type = A $! $! prepare the summary $ analyze/audit/summary/output='summary_file' 'site_audit_archive' $ mail 'summary_file' 'security_manager'- /subject="''site_name' Security Event Summary for ''month_prefix'" $ endif ! analyze test $ endif ! archive name difference test $EXIT: $ if save_privs.nes.null then $ tmp = f$setprv(save_privs) $ vfl = f$ver(vfl) $ exit $!=========================================================================== $! AUDIT_LOG.COM $! $! Abstract: Manage the names of the security audit journal and archive $! files. This procedure is invoked by all of the startup $! procedures in the cluster. It is also invoked by 1 cpu $! just after midnight each day. $! Input: $! p1 type of invocation: 2 valid ones: STARTUP and NEW_DAY $! p2 flag to request analysis of old file if a change occurs $! implicit: old security audit journal file(s) $! Output: $! New security audit journal and/or archive file(s); $! Analysis results for transmission to security manager(s). $! $! Related Procedures: $! SYS$MANAGER:SYSECURITY.COM $! SYS$STARTUP:LOC$SECURITY.COM $! UTL:CLUSTER_DO.COM $! UTL:GETNODE.COM $! UTL:CVTIME.COM $! $! Author: Robert L. Boyd, Harris Semiconductor Microelectronics Ctr. $! $! Date: 4-Jan-1990 $! $! Revision History: $! 3-Jan-90 RLB Initial version written. $! 4-Jan-90 RLB Documentation added. $! 5-Jan-90 RLB Generalized to work with any of the 3 archival methods $! 7-Feb-90 RLB Prepared Template for Shipment $!Last Modified: 7-FEB-1990 08:22:09.81, By: RLB