plaso-rubanetra/plaso/parsers/skydrivelogerr.py
2020-04-06 18:48:34 +02:00

258 lines
8.9 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright 2014 The Plaso Project Authors.
# Please see the AUTHORS file for details on individual authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This file contains SkyDrive error log file parser in plaso."""
import logging
import pyparsing
from plaso.events import time_events
from plaso.lib import eventdata
from plaso.lib import timelib
from plaso.parsers import manager
from plaso.parsers import text_parser
__author__ = 'Francesco Picasso (francesco.picasso@gmail.com)'
class SkyDriveLogErrorEvent(time_events.TimestampEvent):
"""Convenience class for a SkyDrive error log line event."""
DATA_TYPE = 'skydrive:error:line'
def __init__(self, timestamp, module, source_code, text, detail):
"""Initializes the event object.
Args:
timestamp: Milliseconds since epoch in UTC.
module: The module name that generated the log line.
source_code: Logging source file and line number.
text: The error text message.
detail: The error details.
"""
super(SkyDriveLogErrorEvent, self).__init__(
timestamp, eventdata.EventTimestamp.ADDED_TIME)
self.module = module
self.source_code = source_code
self.text = text
self.detail = detail
class SkyDriveLogErrorParser(text_parser.PyparsingMultiLineTextParser):
"""Parse SkyDrive error log files."""
NAME = 'skydrive_log_error'
DESCRIPTION = u'Parser for OneDrive (or SkyDrive) error log files.'
ENCODING = 'utf-8'
# Common SDE (SkyDriveError) structures.
INTEGER_CAST = text_parser.PyParseIntCast
HYPHEN = text_parser.PyparsingConstants.HYPHEN
TWO_DIGITS = text_parser.PyparsingConstants.TWO_DIGITS
TIME_MSEC = text_parser.PyparsingConstants.TIME_MSEC
MSEC = pyparsing.Word(pyparsing.nums, max=3).setParseAction(INTEGER_CAST)
COMMA = pyparsing.Literal(u',').suppress()
DOT = pyparsing.Literal(u'.').suppress()
IGNORE_FIELD = pyparsing.CharsNotIn(u',').suppress()
# Header line timestamp (2013-07-25-160323.291).
SDE_HEADER_TIMESTAMP = pyparsing.Group(
text_parser.PyparsingConstants.DATE.setResultsName('date') + HYPHEN +
TWO_DIGITS.setResultsName('hh') + TWO_DIGITS.setResultsName('mm') +
TWO_DIGITS.setResultsName('ss') + DOT +
MSEC.setResultsName('ms')).setResultsName('hdr_timestamp')
# Line timestamp (07-25-13,16:06:31.820).
SDE_TIMESTAMP = (
TWO_DIGITS.setResultsName('month') + HYPHEN +
TWO_DIGITS.setResultsName('day') + HYPHEN +
TWO_DIGITS.setResultsName('year_short') + COMMA +
TIME_MSEC.setResultsName('time')).setResultsName('timestamp')
# Header start.
SDE_HEADER_START = (
pyparsing.Literal(u'######').suppress() +
pyparsing.Literal(u'Logging started.').setResultsName('log_start'))
# Multiline entry end marker, matched from right to left.
SDE_ENTRY_END = pyparsing.StringEnd() | SDE_HEADER_START | SDE_TIMESTAMP
# SkyDriveError line pyparsing structure.
SDE_LINE = (
SDE_TIMESTAMP + COMMA +
IGNORE_FIELD + COMMA + IGNORE_FIELD + COMMA + IGNORE_FIELD + COMMA +
pyparsing.CharsNotIn(u',').setResultsName('module') + COMMA +
pyparsing.CharsNotIn(u',').setResultsName('source_code') + COMMA +
IGNORE_FIELD + COMMA + IGNORE_FIELD + COMMA + IGNORE_FIELD + COMMA +
pyparsing.Optional(pyparsing.CharsNotIn(u',').setResultsName('text')) +
COMMA + pyparsing.SkipTo(SDE_ENTRY_END).setResultsName('detail') +
pyparsing.lineEnd())
# SkyDriveError header pyparsing structure.
SDE_HEADER = (
SDE_HEADER_START +
pyparsing.Literal(u'Version=').setResultsName('ver_str') +
pyparsing.Word(pyparsing.nums + u'.').setResultsName('ver_num') +
pyparsing.Literal(u'StartSystemTime:').suppress() +
SDE_HEADER_TIMESTAMP +
pyparsing.Literal(u'StartLocalTime:').setResultsName('lt_str') +
pyparsing.SkipTo(pyparsing.lineEnd()).setResultsName('details') +
pyparsing.lineEnd())
# Define the available log line structures.
LINE_STRUCTURES = [
('logline', SDE_LINE),
('header', SDE_HEADER)
]
def __init__(self):
"""Initializes a parser object."""
super(SkyDriveLogErrorParser, self).__init__()
self.use_local_zone = False
def VerifyStructure(self, parser_context, line):
"""Verify that this file is a SkyDrive Error log file.
Args:
parser_context: A parser context object (instance of ParserContext).
line: A single line from the text file.
Returns:
True if this is the correct parser, False otherwise.
"""
try:
parsed_structure = self.SDE_HEADER.parseString(line)
except pyparsing.ParseException:
logging.debug(u'Not a SkyDrive Error log file')
return False
timestamp = self._GetTimestampFromHeader(parsed_structure.hdr_timestamp)
if not timestamp:
logging.debug(
u'Not a SkyDrive Error log file, invalid timestamp {0:s}'.format(
parsed_structure.timestamp))
return False
return True
def ParseRecord(self, parser_context, key, structure):
"""Parse each record structure and return an EventObject if applicable.
Args:
parser_context: A parser context object (instance of ParserContext).
key: An identification string indicating the name of the parsed
structure.
structure: A pyparsing.ParseResults object from a line in the
log file.
Returns:
An event object (instance of EventObject) or None.
"""
if key == 'logline':
return self._ParseLine(structure)
elif key == 'header':
return self._ParseHeader(structure)
else:
logging.warning(
u'Unable to parse record, unknown structure: {0:s}'.format(key))
def _ParseLine(self, structure):
"""Parse a logline and store appropriate attributes."""
timestamp = self._GetTimestampFromLine(structure.timestamp)
if not timestamp:
logging.debug(u'SkyDriveLogError invalid timestamp {0:s}'.format(
structure.timestamp))
return
# Replace newlines with spaces in structure.detail to preserve output.
return SkyDriveLogErrorEvent(
timestamp, structure.module, structure.source_code,
structure.text, structure.detail.replace(u'\n', u' '))
def _ParseHeader(self, structure):
"""Parse header lines and store appropriate attributes.
[u'Logging started.', u'Version=', u'17.0.2011.0627',
[2013, 7, 25], 16, 3, 23, 291, u'StartLocalTime', u'<details>']
Args:
structure: The parsed structure.
Returns:
timestamp: The event or none.
"""
timestamp = self._GetTimestampFromHeader(structure.hdr_timestamp)
if not timestamp:
logging.debug(
u'SkyDriveLogError invalid timestamp {0:d}'.format(
structure.hdr_timestamp))
return
text = u'{0:s} {1:s} {2:s}'.format(
structure.log_start, structure.ver_str, structure.ver_num)
detail = u'{0:s} {1:s}'.format(structure.lt_str, structure.details)
return SkyDriveLogErrorEvent(
timestamp, None, None, text, detail)
def _GetTimestampFromHeader(self, structure):
"""Gets a timestamp from the structure.
The following is an example of the timestamp structure expected
[[2013, 7, 25], 16, 3, 23, 291]
Args:
structure: The parsed structure, which should be a timestamp.
Returns:
timestamp: A plaso timelib timestamp event or 0.
"""
year, month, day = structure.date
hour = structure.get('hh', 0)
minute = structure.get('mm', 0)
second = structure.get('ss', 0)
microsecond = structure.get('ms', 0) * 1000
return timelib.Timestamp.FromTimeParts(
year, month, day, hour, minute, second, microseconds=microsecond)
def _GetTimestampFromLine(self, structure):
"""Gets a timestamp from string from the structure
The following is an example of the timestamp structure expected
[7, 25, 13, [16, 3, 24], 649]
Args:
structure: The parsed structure.
Returns:
timestamp: A plaso timelib timestamp event or 0.
"""
hour, minute, second = structure.time[0]
microsecond = structure.time[1] * 1000
# TODO: Verify if timestamps are locale dependent.
year = structure.get('year_short', 0)
month = structure.get('month', 0)
day = structure.get('day', 0)
if year < 0 or not month or not day:
return 0
year += 2000
return timelib.Timestamp.FromTimeParts(
year, month, day, hour, minute, second, microseconds=microsecond)
manager.ParsersManager.RegisterParser(SkyDriveLogErrorParser)