Source code for plaso.parsers.plist_plugins.time_machine

"""Plist parser plugin for MacOS TimeMachine plist files."""

import os

import pytz

from dfdatetime import time_elements as dfdatetime_time_elements

from plaso.containers import events
from plaso.lib import dtfabric_helper
from plaso.lib import errors
from plaso.parsers import plist
from plaso.parsers.plist_plugins import interface


[docs] class MacOSTimeMachineBackupEventData(events.EventData): """MacOS TimeMachine backup event data. Attributes: backup_alias (str): alias of the backup. destination_identifier (str): identifier of the destination volume. snapshot_times (list[dfdatetime.DateTimeValues]): dates and times of the creation of backup snaphots. """ DATA_TYPE = "macos:time_machine:backup"
[docs] def __init__(self): """Initializes event data.""" super().__init__(data_type=self.DATA_TYPE) self.backup_alias = None self.destination_identifier = None self.snapshot_times = None
[docs] class MacOSTimeMachinePlistPlugin( interface.PlistPlugin, dtfabric_helper.DtFabricHelper ): """Plist parser plugin for MacOS TimeMachine plist files. Further details about the extracted fields: DestinationID: remote UUID hard disk where the backup is done. BackupAlias: structure that contains the extra information from the destinationID. SnapshotDates: list of the backup dates. """ NAME = "time_machine" DATA_FORMAT = "MacOS TimeMachine plist file" PLIST_PATH_FILTERS = frozenset( [interface.PlistPathFilter("com.apple.TimeMachine.plist")] ) PLIST_KEYS = frozenset(["Destinations", "RootVolumeUUID"]) _DEFINITION_FILE = os.path.join(os.path.dirname(__file__), "time_machine.yaml")
[docs] def __init__(self): """Initializes a plist parser plugin.""" super().__init__() self._backup_alias_map = self._GetDataTypeMap("timemachine_backup_alias")
# pylint: disable=arguments-differ def _ParsePlist(self, parser_mediator, match=None, **unused_kwargs): """Extracts relevant MacOS TimeMachine entries. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. match (Optional[dict[str: object]]): keys extracted from PLIST_KEYS. """ for destination in match.get("Destinations", []): backup_alias_string = None snapshot_times = [] backup_alias_data = destination.get("BackupAlias") if backup_alias_data: try: backup_alias = self._ReadStructureFromByteStream( backup_alias_data, 0, self._backup_alias_map ) backup_alias_string = backup_alias.string except (ValueError, TypeError, errors.ParseError) as exception: parser_mediator.ProduceExtractionWarning( f"unable to parse backup alias value with error: {exception!s}" ) for datetime_value in destination.get("SnapshotDates", []): # dfDateTime relies on the time zone but since plistlib does not set # one. datetime_value = datetime_value.replace(tzinfo=pytz.UTC) date_time = dfdatetime_time_elements.TimeElementsInMicroseconds() date_time.CopyFromDatetime(datetime_value) snapshot_times.append(date_time) event_data = MacOSTimeMachineBackupEventData() event_data.backup_alias = backup_alias_string event_data.destination_identifier = destination.get("DestinationID") event_data.snapshot_times = snapshot_times or None parser_mediator.ProduceEventData(event_data)
plist.PlistParser.RegisterPlugin(MacOSTimeMachinePlistPlugin)