dissect.target.plugins.os.unix.log.journal#

Module Contents#

Classes#

JournalFile

Parse Systemd Journal file format.

JournalPlugin

Base class for plugins.

Functions#

get_optional

Return the value if True, otherwise return None.

Attributes#

dissect.target.plugins.os.unix.log.journal.JournalRecord#
dissect.target.plugins.os.unix.log.journal.journal_def = Multiline-String#
Show Value
"""
typedef uint8 uint8_t;
typedef uint32 le32_t;
typedef uint64 le64_t;

enum State : uint8_t {
    OFFLINE   =  0,
    ONLINE    =  1,
    ARCHIVED  =  2,
    UNKNOWN
};

union sd_id128_t {
    uint8_t   bytes[16];
    uint64_t  qwords[2];
};

flag IncompatibleFlag : le32_t {
    HEADER_INCOMPATIBLE_COMPRESSED_XZ   = 1,
    HEADER_INCOMPATIBLE_COMPRESSED_LZ4  = 2,
    HEADER_INCOMPATIBLE_KEYED_HASH      = 4,
    HEADER_INCOMPATIBLE_COMPRESSED_ZSTD = 8,
    HEADER_INCOMPATIBLE_COMPACT         = 16,             // indicates that the Journal file uses the new binary format
};

struct Header {
    uint8_t           signature[8];
    le32_t            compatible_flags;
    IncompatibleFlag  incompatible_flags;
    State             state;
    uint8_t           reserved[7];
    sd_id128_t        file_id;
    sd_id128_t        machine_id;
    sd_id128_t        tail_entry_boot_id;
    sd_id128_t        seqnum_id;
    le64_t            header_size;
    le64_t            arena_size;
    le64_t            data_hash_table_offset;
    le64_t            data_hash_table_size;
    le64_t            field_hash_table_offset;
    le64_t            field_hash_table_size;
    le64_t            tail_object_offset;
    le64_t            n_objects;
    le64_t            n_entries;
    le64_t            tail_entry_seqnum;
    le64_t            head_entry_seqnum;
    le64_t            entry_array_offset;
    le64_t            head_entry_realtime;
    le64_t            tail_entry_realtime;
    le64_t            tail_entry_monotonic;
    le64_t            n_data;
    le64_t            n_fields;
    le64_t            n_tags;
    le64_t            n_entry_arrays;
    le64_t            data_hash_chain_depth;
    le64_t            field_hash_chain_depth;
    le32_t            tail_entry_array_offset;
    le32_t            tail_entry_array_n_entries;
    le64_t            tail_entry_offset;
};

enum ObjectType : uint8 {
    OBJECT_UNUSED,
    OBJECT_DATA,
    OBJECT_FIELD,
    OBJECT_ENTRY,
    OBJECT_DATA_HASH_TABLE,
    OBJECT_FIELD_HASH_TABLE,
    OBJECT_ENTRY_ARRAY,
    OBJECT_TAG,
    _OBJECT_TYPE_MAX
};

flag ObjectFlag : uint8 {
    OBJECT_UNCOMPRESSED      =  0,
    OBJECT_COMPRESSED_XZ     =  1,
    OBJECT_COMPRESSED_LZ4    =  2,
    OBJECT_COMPRESSED_ZSTD   =  4,
    _OBJECT_COMPRESSED_MASK  =  7
};

struct ObjectHeader {
    ObjectType  type;                                     // The type field is one of the object types listed above
    uint8_t     flags;                                    // If DATA object the value is ObjectFlag
    uint8_t     reserved[6];
    le64_t      size;                                     // The size field encodes the size of the object including all its headers and payload
};


// The first four members are copied from ObjectHeader, so that the size can be used as the length of payload
struct DataObject {
    ObjectType  type;
    ObjectFlag  flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      hash;
    le64_t      next_hash_offset;
    le64_t      next_field_offset;
    le64_t      entry_offset;
    le64_t      entry_array_offset;
    le64_t      n_entries;
    char        payload[size - 64];                       // Data objects carry actual field data in the payload[] array.
};

// If the HEADER_INCOMPATIBLE_COMPACT flag is set, two extra fields are stored to allow immediate access
// to the tail entry array in the DATA object's entry array chain.
struct DataObject_Compact {
    ObjectType  type;
    ObjectFlag  flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      hash;
    le64_t      next_hash_offset;
    le64_t      next_field_offset;
    le64_t      entry_offset;
    le64_t      entry_array_offset;
    le64_t      n_entries;
    le32_t      tail_entry_array_offset;
    le32_t      tail_entry_array_n_entries;
    char        payload[size - 72];                       // Data objects carry actual field data in the payload[] array.
};

struct EntryItem {
    le64_t object_offset;
    le64_t hash;
};

struct EntryItem_Compact {
    le32_t object_offset;
}

// The first four members are copied from ObjectHeader, so that the size can be used as the length of items
struct EntryObject {
    ObjectType  type;
    uint8_t     flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      seqnum;
    le64_t      realtime;
    le64_t      monotonic;
    sd_id128_t  boot_id;
    le64_t      xor_hash;
    EntryItem   items[(size - 64) / 16];                  // The size minus the previous members divided by the size of the items
};

// If the HEADER_INCOMPATIBLE_COMPACT flag is set, DATA object offsets are stored as 32-bit integers instead of 64bit
// and the unused hash field per data object is not stored anymore.
struct EntryObject_Compact {
    ObjectType  type;
    uint8_t     flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      seqnum;
    le64_t      realtime;
    le64_t      monotonic;
    sd_id128_t  boot_id;
    le64_t      xor_hash;
    EntryItem_Compact   items[(size - 64) / 4];
};

// The first four members are copied from from ObjectHeader, so that the size can be used as the length of entry_object_offsets
struct EntryArrayObject {
    ObjectType  type;
    uint8_t     flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      next_entry_array_offset;
    le64_t      entry_object_offsets[(size - 24) / 8];    // The size minus the previous members divided by the size of the offset
};

struct EntryArrayObject_Compact {
    ObjectType  type;
    uint8_t     flags;
    uint8_t     reserved[6];
    le64_t      size;
    le64_t      next_entry_array_offset;
    le32_t      entry_object_offsets[(size - 24) / 4];
};
"""
dissect.target.plugins.os.unix.log.journal.c_journal#
dissect.target.plugins.os.unix.log.journal.get_optional(value: str, to_type: Callable)#

Return the value if True, otherwise return None.

class dissect.target.plugins.os.unix.log.journal.JournalFile(fh: BinaryIO, target: dissect.target.Target)#

Parse Systemd Journal file format.

References

entry_object_offsets() Iterator[int]#

Read object entry arrays.

decode_value(value: bytes) tuple[str, str]#
__iter__() Iterator[dissect.cstruct.Instance]#

Iterate over the entry objects to read payloads.

class dissect.target.plugins.os.unix.log.journal.JournalPlugin(target: dissect.target.Target)#

Bases: dissect.target.plugin.Plugin

Base class for plugins.

Plugins can optionally be namespaced by specifying the __namespace__ class attribute. Namespacing results in your plugin needing to be prefixed with this namespace when being called. For example, if your plugin has specified test as namespace and a function called example, you must call your plugin with test.example:

A Plugin class has the following private class attributes:

  • __namespace__

  • __record_descriptors__

With the following three being assigned in register():

  • __plugin__

  • __functions__

  • __exports__

Additionally, the methods and attributes of Plugin receive more private attributes by using decorators.

The export() decorator adds the following private attributes

  • __exported__

  • __output__: Set with the export() decorator.

  • __record__: Set with the export() decorator.

The internal() decorator and InternalPlugin set the __internal__ attribute. Finally. args() decorator sets the __args__ attribute.

Parameters:

target – The Target object to load the plugin for.

JOURNAL_PATHS = ['/var/log/journal']#
JOURNAL_GLOB = '*/*.journal*'#
JOURNAL_SIGNATURE = 'LPKSHHRH'#
check_compatible() None#

Perform a compatibility check with the target.

This function should return None if the plugin is compatible with the current target (self.target). For example, check if a certain file exists. Otherwise it should raise an UnsupportedPluginError.

Raises:

UnsupportedPluginError – If the plugin could not be loaded.

journal() Iterator[JournalRecord]#

Return the content of Systemd Journal log files.

References