/* -------------------------------------------------------------------------------- SPADE - Support for Provenance Auditing in Distributed Environments. Copyright (C) 2015 SRI International This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. -------------------------------------------------------------------------------- */ package spade.reporter.audit; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.exception.ExceptionUtils; import spade.core.Settings; import spade.utility.HelperFunctions; import spade.utility.FileUtility; /** * This class reads and parses the audit logs one event at a time. * * Assumes that the all of the records for an event are received * contiguously and are not spread out. * */ public class AuditEventReader { private Logger logger = Logger.getLogger(this.getClass().getName()); public static final String ARG0 = "a0", ARG1 = "a1", ARG2 = "a2", ARG3 = "a3", COMM = "comm", CWD = "cwd", DADDR = "daddr", DPORT = "dport", EGID = "egid", EUID = "euid", EVENT_ID = "eventid", EXECVE_ARGC = "execve_argc", EXECVE_PREFIX = "execve_", EXIT = "exit", FD = "fd", FD0 = "fd0", FD1 = "fd1", FSGID = "fsgid", FSUID = "fsuid", GID = "gid", HOOK = "hook", HOOK_INPUT = "1", HOOK_OUTPUT = "3", ITEMS = "items", MODE_PREFIX = "mode", NAMETYPE_CREATE = "CREATE", NAMETYPE_DELETE = "DELETE", NAMETYPE_NORMAL = "NORMAL", NAMETYPE_PARENT = "PARENT", NAMETYPE_PREFIX = "nametype", NAMETYPE_UNKNOWN = "UNKNOWN", PATH_PREFIX = "path", PID = "pid", PPID = "ppid", PROTO = "proto", RECORD_TYPE_CWD = "CWD", RECORD_TYPE_DAEMON_START = "DAEMON_START", RECORD_TYPE_EOE = "EOE", RECORD_TYPE_EXECVE = "EXECVE", RECORD_TYPE_FD_PAIR = "FD_PAIR", RECORD_TYPE_MMAP = "MMAP", RECORD_TYPE_NETFILTER_PKT = "NETFILTER_PKT", RECORD_TYPE_PATH = "PATH", RECORD_TYPE_PROCTITLE = "PROCTITLE", RECORD_TYPE_SOCKADDR = "SOCKADDR", RECORD_TYPE_SOCKETCALL = "SOCKETCALL", RECORD_TYPE_SYSCALL = "SYSCALL", RECORD_TYPE_UBSI_ENTRY = "UBSI_ENTRY", RECORD_TYPE_UBSI_EXIT = "UBSI_EXIT", RECORD_TYPE_UBSI_DEP = "UBSI_DEP", RECORD_TYPE_UNKNOWN_PREFIX = "UNKNOWN[", RECORD_TYPE_USER = "USER", RECORD_TYPE_KEY = "type", SADDR = "saddr", SGID = "sgid", SPORT = "sport", SUCCESS = "success", SUCCESS_NO = "no", SUCCESS_YES = "yes", SUID = "suid", SYSCALL = "syscall", TIME = "time", UID = "uid", UNIT_PID = "unit_pid", UNIT_THREAD_START_TIME = "unit_thread_start_time", UNIT_UNITID = "unit_unitid", UNIT_ITERATION = "unit_iteration", UNIT_TIME = "unit_time", UNIT_COUNT = "unit_count", UNIT_DEPS_COUNT = "unit_deps_count", USER_MSG_SPADE_AUDIT_HOST_KEY = "spade_host_msg", KMODULE_RECORD_TYPE = "netio_module_record", KMODULE_DATA_KEY = "netio_intercepted", UBSI_INTERCEPTED_DATA_KEY = "ubsi_intercepted", KMODULE_FD = "fd", KMODULE_SOCKTYPE = "sock_type", KMODULE_LOCAL_SADDR = "local_saddr", KMODULE_REMOTE_SADDR = "remote_saddr", NS_SUBTYPE_KEY = "ns_subtype", NS_SUBTYPE_VALUE = "ns_namespaces", NS_OPERATION_KEY = "ns_operation", NS_OPERATION_VALUE_NEWPROCESS = "ns_NEWPROCESS", NS_SYSCALL_KEY = "ns_syscall", NS_NS_PID = "ns_ns_pid", NS_HOST_PID = "ns_host_pid", NS_INUM_MNT = "ns_inum_mnt", NS_INUM_NET = "ns_inum_net", NS_INUM_PID = "ns_inum_pid", NS_INUM_PID_FOR_CHILDREN = "ns_inum_pid_children", NS_INUM_USER = "ns_inum_usr", NS_INUM_IPC = "ns_inum_ipc"; //Reporting variables private boolean reportingEnabled = false; private long reportEveryMs; private long startTime, lastReportedTime; private long lastReportedRecordCount, recordCount; // Group 1: pid // Group 2: unitid // Group 3: iteration // Group 4: time // Group 5: count private final Pattern pattern_unit = Pattern.compile("\\(pid=(\\d+) thread_time=(\\d+\\.\\d+) unitid=(\\d+) iteration=(\\d+) time=(\\d+\\.\\d+) count=(\\d+)\\)"); // Group 1: key // Group 2: value private final Pattern pattern_key_value = Pattern.compile("(\\w+)=\"*((?<=\")[^\"]+(?=\")|([^\\s]+))\"*"); // Group 1: node // Group 2: type // Group 3: time // Group 4: recordid private final Pattern pattern_message_start = Pattern.compile("(?:node=(\\S+) )?type=(.+) msg=audit\\(([0-9\\.]+)\\:([0-9]+)\\):\\s*"); // Group 1: cwd //cwd is either a quoted string or an unquoted string in which case it is in hex format private final Pattern pattern_cwd = Pattern.compile("cwd=(\".+\"|[a-zA-Z0-9]+)"); // Group 1: item number // Group 2: name // Group 3: mode // Group 4: nametype //name is either a quoted string or an unquoted string in which case it is in hex format // private static final Pattern pattern_path = Pattern.compile("item=([0-9]*) name=(\".+\"|[a-zA-Z0-9]+|\\(null\\)) .*(?:mode=([0-9]+) ).*nametype=([a-zA-Z]*)"); /** * Buffers all the records for the current event being read */ private final Set<String> currentEventRecords = new HashSet<String>(); /** * Keeps track of the current event id being buffered */ private Long currentEventId = -1L; /** * Id of the stream that is read by this class */ private String streamId; /** * The stream to read from by this class */ private BufferedReader stream; private long rotateAfterRecordCount = 0; private String outputLogFile = null; private PrintWriter outputLogWriter = null; private int currentOutputLogFileCount = 0; private long recordsWrittenToOutputLog = 0; /** * Used to find out if there is pending UBSI event before reading more */ private boolean pendingUBSIEvent = false; /** * Flag to keep track of end of file/stream */ private boolean EOF = false; /** * Flag to tell the reader how to behave in case of unexpected data format. * if true then throw an exception. * if false then do best effort to continue. */ private boolean failfast; /** * Create instance of the class that reads from the given stream * * @param streamId An identifier to read the audit logs from * @param streamToReadFrom The stream to read from * @throws Exception IllegalArgumentException or IOException */ public AuditEventReader(String streamId, InputStream streamToReadFrom, boolean failfast) throws Exception{ if(streamId == null){ throw new IllegalArgumentException("Stream ID cannot be NULL"); } if(streamToReadFrom == null){ throw new IllegalArgumentException("The stream to read from cannot be NULL"); } stream = new BufferedReader(new InputStreamReader(streamToReadFrom)); this.failfast = failfast; setGlobalsFromConfig(); } private void setGlobalsFromConfig(){ String defaultConfigFilePath = Settings.getDefaultConfigFilePath(this.getClass()); try{ if(new File(defaultConfigFilePath).exists()){ Map<String, String> properties = FileUtility.readConfigFileAsKeyValueMap(defaultConfigFilePath, "="); if(properties != null && properties.size() > 0){ Long reportingInterval = HelperFunctions.parseLong(properties.get("reportingIntervalSeconds"), null); if(reportingInterval != null){ if(reportingInterval < 1){ //at least 1 ms logger.log(Level.INFO, "Statistics reporting turned off"); }else{ reportingEnabled = true; reportEveryMs = reportingInterval * 1000; startTime = lastReportedTime = System.currentTimeMillis(); recordCount = lastReportedRecordCount = 0; } } } } }catch(Exception e){ logger.log(Level.SEVERE, "Failed to read config file '"+defaultConfigFilePath+"'"); } } /** * Function to set the output log file to which the log is written * * If rotateAfterRecordCount is less than 1 then no rotation is done and * everything is written to a single file. * * @param outputLogFile output log file to write to * @param rotateAfterRecordCount number of records to create a new log after * @throws Exception IOException */ public void setOutputLog(String outputLogFile, long rotateAfterRecordCount) throws Exception{ this.outputLogFile = outputLogFile; this.rotateAfterRecordCount = rotateAfterRecordCount < 1 ? 0 : rotateAfterRecordCount; outputLogWriter = new PrintWriter(outputLogFile); } private void writeToOutputLog(String record){ if(outputLogWriter != null){ try{ outputLogWriter.println(record); recordsWrittenToOutputLog++; if(rotateAfterRecordCount > 0 && recordsWrittenToOutputLog >= rotateAfterRecordCount){ recordsWrittenToOutputLog = 0; currentOutputLogFileCount++; outputLogWriter.flush(); outputLogWriter.close(); outputLogWriter = new PrintWriter(outputLogFile + "." + currentOutputLogFileCount); } }catch(Exception e){ logger.log(Level.WARNING, "Failed to write out to output log", e); } } } private void printStats(){ long currentTime = System.currentTimeMillis(); float overallTime = (float) (currentTime - startTime) / 1000; // # in secs float intervalTime = (float) (currentTime - lastReportedTime) / 1000; // # in secs if(overallTime > 0 && intervalTime > 0){ float overallRecordVolume = (float) recordCount / overallTime; // # records/sec float intervalRecordVolume = (float) (recordCount - lastReportedRecordCount) / intervalTime; // # records/sec logger.log(Level.INFO, "Overall rate: {0} records/sec in {1} seconds. Interval rate: {2} records/sec in {3} seconds.", new Object[]{overallRecordVolume, overallTime, intervalRecordVolume, intervalTime}); } } /** * Returns the event id from the audit record. * * Expected format of line -> "type='TYPE' msg=audit('time':'eventid'):" * * @param line audit record * @return event id. NULL if not found */ private Long getEventId(String line){ try{ int firstIndexOfColon = line.indexOf(':'); int firstIndexOfClosingBracket = line.indexOf(')'); return Long.parseLong(line.substring(firstIndexOfColon+1, firstIndexOfClosingBracket)); }catch(Exception e){ logger.log(Level.WARNING, "Failed to get event id from line: " + line, e); return null; } } /** * Returns the time from the audit record. * * Expected format of line -> "type='TYPE' msg=audit('time':'eventid'):" * * @param line audit record * @return time. NULL if not found */ private String getEventTime(String line){ try{ int firstIndexOfOpeningBracket = line.indexOf('('); int firstIndexOfColon = line.indexOf(':'); String timeStr = line.substring(firstIndexOfOpeningBracket+1, firstIndexOfColon); Double.parseDouble(timeStr); // if valid double then continues return timeStr; }catch(Exception e){ logger.log(Level.WARNING, "Failed to get time from line: " + line, e); return null; } } /** * Returns a map of key values for the event that is read from the stream * * Null return value means EOF * * Reads on the assumption that all records for an event are contiguously placed * * @return map of key values of the read audit event * @throws Exception IOException */ public Map<String, String> readEventData() throws Exception{ if(reportingEnabled){ long currentTime = System.currentTimeMillis(); if((currentTime - lastReportedTime) >= reportEveryMs){ printStats(); lastReportedTime = currentTime; lastReportedRecordCount = recordCount; } } /* * Logic: * * Input -> all records have event ids exception UBSI_EXIT and UBSI_DEP * All UBSI events have only one record per event * * Before reading further from the stream check if there is a pending UBSI * event. If there is then don't read from the stream yet and return the * pending event. If no pending UBSI event then read from the stream. If non- * UBSI records being read then read until the event id changes and then return * the event that is read so far. If UBSI event encountered while there is a * non-UBSI event buffered then first return that event (after setting pending- * UBSIEvent to true and buffering that for the next readEventData call. * * If EOF reached then keep returning NULL on all future calls. * */ if(EOF){ return null; }else{ Map<String, String> eventData = null; if(pendingUBSIEvent){ Set<String> copy = new HashSet<String>(); copy.addAll(currentEventRecords); currentEventRecords.clear(); currentEventId = -1L; pendingUBSIEvent = false; eventData = getEventMap(copy); }else{ String line = null; while((line = stream.readLine()) != null){ Long eventId = getEventId(line); String eventTime = getEventTime(line); if(eventId == null || eventTime == null){ if(failfast){ throw new Exception("Invalid time '"+eventTime+"' or event-id '"+eventId+"' in record: " + line); }else{ continue; } } writeToOutputLog(line); if(reportingEnabled){ recordCount++; } if(line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_PROCTITLE) || line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_UNKNOWN_PREFIX) || line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_EOE)){ continue; // ignore these records }else{ String UBSIRecord = null; if(line.contains(RECORD_TYPE_KEY+"=" + RECORD_TYPE_UBSI_EXIT) || line.contains(RECORD_TYPE_KEY+"=" + RECORD_TYPE_UBSI_DEP) || line.contains(RECORD_TYPE_KEY+"=" + RECORD_TYPE_UBSI_ENTRY)){ UBSIRecord = line; } if(UBSIRecord == null){ if(currentEventId.equals(-1L)){ currentEventId = eventId; currentEventRecords.add(line); //add the next event record continue; }else{ if(!currentEventId.equals(eventId)){// event id changed hence publish the things in buffer currentEventId = eventId; Set<String> records = new HashSet<String>(currentEventRecords); currentEventRecords.clear(); currentEventRecords.add(line); //add the next event record eventData = getEventMap(records); break; }else{ //if they are equal currentEventRecords.add(line); continue; } } }else if(UBSIRecord != null && currentEventRecords.isEmpty()){ // No pending event and only UBSI event then return that Set<String> records = new HashSet<String>(); records.add(UBSIRecord); currentEventId = -1L; pendingUBSIEvent = false; eventData = getEventMap(records); break; }else if(UBSIRecord != null && !currentEventRecords.isEmpty()){ // Has a pending event. add the UBSI record to pending and return the existing event Set<String> records = new HashSet<String>(currentEventRecords); currentEventRecords.clear(); currentEventRecords.add(UBSIRecord); currentEventId = -1L; pendingUBSIEvent = true; eventData = getEventMap(records); break; } } } // EOF if(line == null){ EOF = true; if(currentEventRecords.isEmpty()){ return null; }else{ Set<String> records = new HashSet<String>(currentEventRecords); currentEventRecords.clear(); currentEventId = -1L; pendingUBSIEvent = false; return getEventMap(records); } } } return eventData; } } /** * Passes all the records through the function {@link #parseEventLine(String) parseEventLine} * and returns a map which contains keys and values for all the records * * @param records records of a single event * @return map of key values */ private Map<String, String> getEventMap(Set<String> records) throws Exception{ try{ Map<String, String> eventMap = new HashMap<String, String>(); for(String record : records){ eventMap.putAll(parseEventLine(record)); } return eventMap; }catch(Exception e){ throw new MalformedAuditDataException(e.getMessage()+ " ["+ExceptionUtils.getStackTrace(e)+"] ", String.valueOf(records)); } } public void close(){ if(reportingEnabled){ printStats(); } if(outputLogWriter != null){ try{ outputLogWriter.close(); }catch(Exception e){ logger.log(Level.SEVERE, "Failed to close output log writer", e); } } if(stream != null){ try{ stream.close(); }catch(Exception e){ logger.log(Level.SEVERE, "Failed to close the stream '"+streamId+"'", e); } } } /** * Parses the line to get unit information out of it. * * Expected format for unit information ...'(pid=1 unitid=2 iteration=3 time=4 count=5)'... * * Returns a map which contains the keys in the above-given format but the keys are * defined as constants in this class. * * @param line audit record with unit information * @return map of key values for a unit */ private List<Map<String, String>> parseUnitsKeyValues(String line){ List<Map<String, String>> unitsKeyValues = new ArrayList<Map<String, String>>(); Matcher matcher2 = pattern_unit.matcher(line); while(matcher2.find()){ String pid = matcher2.group(1); String thread_start_time = matcher2.group(2); String unitid = matcher2.group(3); String iteration = matcher2.group(4); String time = matcher2.group(5); String count = matcher2.group(6); Map<String, String> unitKeyValues = new HashMap<String, String>(); unitKeyValues.put(UNIT_PID, pid); unitKeyValues.put(UNIT_THREAD_START_TIME, thread_start_time); unitKeyValues.put(UNIT_UNITID, unitid); unitKeyValues.put(UNIT_ITERATION, iteration); unitKeyValues.put(UNIT_TIME, time); unitKeyValues.put(UNIT_COUNT, count); unitsKeyValues.add(unitKeyValues); } return unitsKeyValues; } private String _parseAuditString(String originalRecord, String key){ int keyStartIndex = originalRecord.indexOf(key); if(keyStartIndex < 0){ return null; }else{ int valueStartIndex = keyStartIndex + key.length(); if(valueStartIndex >= originalRecord.length()){ return null; }else{ char valueFirstChar = originalRecord.charAt(valueStartIndex); if(valueFirstChar == '"'){ // is quoted string int valueEndIndex = originalRecord.indexOf('"', valueStartIndex + 1); if(valueEndIndex < 0){ return null; }else{ return originalRecord.substring(valueStartIndex+1, valueEndIndex); } }else{ // is hex string int valueEndIndex = originalRecord.indexOf(' ', valueStartIndex + 1); if(valueEndIndex < 0){ valueEndIndex = originalRecord.length(); } String hexValue = originalRecord.substring(valueStartIndex, valueEndIndex); return HelperFunctions.decodeHex(hexValue); } } } } /** * Creates a map with key values as needed by the Audit reporter from audit records of an event * * @param line event record to parse * @return map of key values for the argument record */ private Map<String, String> parseEventLine(String line) { Map<String, String> auditRecordKeyValues = new HashMap<String, String>(); if(line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_DAEMON_START)){ auditRecordKeyValues.put(RECORD_TYPE_KEY, RECORD_TYPE_DAEMON_START); return auditRecordKeyValues; } boolean isUBSIEvent = false; // There will be time and eventid in this one if(line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_UBSI_ENTRY)){ List<Map<String, String>> unitsKeyValues = parseUnitsKeyValues(line); if(unitsKeyValues.size() != 1){ // there should be only one unit's information logger.log(Level.WARNING, "Malformed record '"+line+"'"); }else{ // Add all the units key values auditRecordKeyValues.putAll(unitsKeyValues.get(0)); } auditRecordKeyValues.put(AuditEventReader.RECORD_TYPE_KEY, RECORD_TYPE_UBSI_ENTRY); isUBSIEvent = true; }else if(line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_UBSI_EXIT)){ // no time and event id auditRecordKeyValues.put(AuditEventReader.RECORD_TYPE_KEY, RECORD_TYPE_UBSI_EXIT); isUBSIEvent = true; }else if(line.contains(RECORD_TYPE_KEY+"="+RECORD_TYPE_UBSI_DEP)){ // no time and event id List<Map<String, String>> unitsKeyValues = parseUnitsKeyValues(line); if(unitsKeyValues.size() == 0){ // there should be only one or more unit's information logger.log(Level.WARNING, "Malformed record '"+line+"'"); }else{ // Add all the units key values // Last one is the acting unit Map<String, String> actingUnitKeyValues = unitsKeyValues.remove(unitsKeyValues.size() - 1); auditRecordKeyValues.putAll(actingUnitKeyValues); for(int a = 0; a<unitsKeyValues.size(); a++){ Map<String, String> unitKeyValues = unitsKeyValues.get(a); for(Map.Entry<String, String> entry : unitKeyValues.entrySet()){ auditRecordKeyValues.put(entry.getKey() + a, entry.getValue()); } } auditRecordKeyValues.put(UNIT_DEPS_COUNT, String.valueOf(unitsKeyValues.size())); } auditRecordKeyValues.put(AuditEventReader.RECORD_TYPE_KEY, RECORD_TYPE_UBSI_DEP); isUBSIEvent = true; } if(isUBSIEvent){ Long UBSIEntryEventId = getEventId(line); String UBSIEntryTime = getEventTime(line); auditRecordKeyValues.put(TIME, UBSIEntryTime); auditRecordKeyValues.put(EVENT_ID, String.valueOf(UBSIEntryEventId)); String msgData = line.substring(line.indexOf(" ppid=")); auditRecordKeyValues.putAll(HelperFunctions.parseKeyValPairs(msgData)); String comm = _parseAuditString(line, " comm="); auditRecordKeyValues.put(COMM, comm); }else{ Matcher event_start_matcher = pattern_message_start.matcher(line); if (event_start_matcher.find()) { String type = event_start_matcher.group(2); String time = event_start_matcher.group(3); String eventId = event_start_matcher.group(4); String messageData = line.substring(event_start_matcher.end()); auditRecordKeyValues.put(EVENT_ID, eventId); auditRecordKeyValues.put(RECORD_TYPE_KEY, type); if(type.equals(RECORD_TYPE_USER)){ Map<String, String> nsEventData = HelperFunctions.parseKeyValPairs(messageData); if(NS_SUBTYPE_VALUE.equals(nsEventData.get(NS_SUBTYPE_KEY))){ auditRecordKeyValues.putAll(nsEventData); }else{ int indexOfData = messageData.indexOf(KMODULE_DATA_KEY); if(indexOfData != -1){ String data = messageData.substring(indexOfData + KMODULE_DATA_KEY.length() + 1); data = data.substring(1, data.length() - 1);// remove quotes Map<String, String> eventData = HelperFunctions.parseKeyValPairs(data); eventData.put(RECORD_TYPE_KEY, KMODULE_RECORD_TYPE); eventData.put(COMM, HelperFunctions.decodeHex(eventData.get(COMM))); eventData.put(TIME, time); auditRecordKeyValues.putAll(eventData); }else{ indexOfData = messageData.indexOf(UBSI_INTERCEPTED_DATA_KEY); if(indexOfData != -1){ String data = messageData .substring(indexOfData + UBSI_INTERCEPTED_DATA_KEY.length() + 1); data = data.substring(1, data.length() - 1);// remove quotes Map<String, String> eventData = HelperFunctions.parseKeyValPairs(data); eventData.put(RECORD_TYPE_KEY, RECORD_TYPE_SYSCALL); eventData.put(COMM, HelperFunctions.decodeHex(eventData.get(COMM))); eventData.put(TIME, time); auditRecordKeyValues.putAll(eventData); }else{ indexOfData = messageData.indexOf(" syscall=62 "); Map<String, String> eventData = HelperFunctions.parseKeyValPairs(messageData); eventData.put(RECORD_TYPE_KEY, RECORD_TYPE_SYSCALL); eventData.put(COMM, HelperFunctions.decodeHex(eventData.get(COMM))); eventData.put(TIME, time); auditRecordKeyValues.putAll(eventData); } } } }else if (type.equals(RECORD_TYPE_SYSCALL)) { Map<String, String> eventData = HelperFunctions.parseKeyValPairs(messageData); String commValue = _parseAuditString(line, " comm="); eventData.put(COMM, commValue); eventData.put(TIME, time); auditRecordKeyValues.putAll(eventData); } else if (type.equals(RECORD_TYPE_CWD)) { String cwd = _parseAuditString(line, " cwd="); auditRecordKeyValues.put(CWD, cwd); } else if (type.equals(RECORD_TYPE_PATH)) { Map<String, String> pathKeyValues = HelperFunctions.parseKeyValPairs(messageData); String itemNumber = pathKeyValues.get("item"); String mode = pathKeyValues.get("mode"); mode = mode == null ? "0" : mode; String nametype = pathKeyValues.get("nametype"); String name = _parseAuditString(line, " name="); auditRecordKeyValues.put(PATH_PREFIX + itemNumber, name); auditRecordKeyValues.put(NAMETYPE_PREFIX + itemNumber, nametype); auditRecordKeyValues.put(MODE_PREFIX + itemNumber, mode); } else if (type.equals(RECORD_TYPE_EXECVE)) { Map<String, String> tempKeyValues = HelperFunctions.parseKeyValPairs(line); String argcString = tempKeyValues.get("argc"); auditRecordKeyValues.put(EXECVE_ARGC, argcString); Integer argc = HelperFunctions.parseInt(argcString, null); if(argc != null){ for(int i = 0; i < argc; i++){ String key = "a"+i; String keyForGettingValue = " " + key + "="; String value = _parseAuditString(line, keyForGettingValue); String prefixedKey = EXECVE_PREFIX + key; auditRecordKeyValues.put(prefixedKey, value); } } } else if (type.equals(RECORD_TYPE_FD_PAIR)) { Matcher key_value_matcher = pattern_key_value.matcher(messageData); while (key_value_matcher.find()) { auditRecordKeyValues.put(key_value_matcher.group(1), key_value_matcher.group(2)); } } else if (type.equals(RECORD_TYPE_SOCKETCALL)) { Matcher key_value_matcher = pattern_key_value.matcher(messageData); while (key_value_matcher.find()) { auditRecordKeyValues.put("socketcall_" + key_value_matcher.group(1), key_value_matcher.group(2)); } } else if (type.equals(RECORD_TYPE_SOCKADDR)) { Matcher key_value_matcher = pattern_key_value.matcher(messageData); while (key_value_matcher.find()) { auditRecordKeyValues.put(key_value_matcher.group(1), key_value_matcher.group(2)); } } else if(type.equals(RECORD_TYPE_NETFILTER_PKT)){ auditRecordKeyValues.put(TIME, time); // add time auditRecordKeyValues.put(RECORD_TYPE_KEY, RECORD_TYPE_NETFILTER_PKT); // type // rest of the keys as is below Matcher key_value_matcher = pattern_key_value.matcher(messageData); while (key_value_matcher.find()) { auditRecordKeyValues.put(key_value_matcher.group(1), key_value_matcher.group(2)); } } else if (type.equals(RECORD_TYPE_MMAP)){ Matcher key_value_matcher = pattern_key_value.matcher(messageData); while (key_value_matcher.find()) { auditRecordKeyValues.put(key_value_matcher.group(1), key_value_matcher.group(2)); } } else{ } } else { } } return auditRecordKeyValues; } }