Parsing Context¶
pcapkit.corekit.context provides a protocol-keyed channel for
caller-supplied information that a protocol needs to parse a packet but that
is not carried on the wire.
Most protocols are self-describing: every length, offset and type needed to
walk a packet is in the packet. A few are not, and
ESP is the motivating example:
RFC 4303 deliberately leaves the payload length, the position of the
Pad Length / Next Header trailer and the length of the Integrity
Check Value to the Security Association (SA), which is negotiated out of band
and known only to the caller.
Rather than adding protocol-specific keyword arguments to
Extractor, such information is passed
as a ContextRegistry – a mapping of protocol
index ID (c.f. Protocol.id) to
a ProtocolContext instance. It is handed to
Extractor once and propagated down the
protocol stack by
Protocol._import_next_layer,
so that a protocol nested arbitrarily deep can reach it through
Protocol._get_context.
Decoding an ESP tunnel end to end:
>>> import pcapkit
>>> from pcapkit.protocols.internet.esp import (Cipher, ESPContext,
... Integrity, SecurityAssociation)
>>> sa = SecurityAssociation(
... spi=0x4321,
... encryption=Cipher.AES_CBC,
... encryption_key=bytes.fromhex('90d382b410eeba7ad938c46cec1a82bf'),
... )
>>> extraction = pcapkit.extract('esp.pcap', context=ESPContext(sa))
Important
A context often holds secrets, such as ESP encryption and integrity keys.
Contexts are therefore plain instance attributes on the protocol object and
are never written into its data model, which is the only thing that
reaches Info.to_dict and,
from there, the output dumpers.
ProtocolContext implementations are
expected to keep secrets out of their __repr__() as well.
- class pcapkit.corekit.context.ProtocolContext[source]¶
Bases:
objectAbstract base class for caller supplied protocol parsing context.
A subclass carries whatever out-of-band information the corresponding protocol needs, and declares which protocol it applies to through
protocol().Warning
Should the context hold secrets, the subclass must override
__repr__()so that they are not printed. The default implementation below prints the class name and the protocol names only, and is safe in that respect.- abstractmethod classmethod protocol()[source]¶
Index ID of the protocol(s) this context applies to.
The returned names are matched against
Protocol.id, and are case insensitive.
- class pcapkit.corekit.context.ContextRegistry(*contexts, **named)[source]¶
Bases:
Mapping[str, ProtocolContext]Protocol keyed collection of
ProtocolContextinstances.- Parameters:
*contexts (
ProtocolContext) – Context instances, each keyed by its ownProtocolContext.protocol().**named (
ProtocolContext) – Context instances keyed explicitly by protocol index ID.
- register(context, *, name=None)[source]¶
Register
contextunder one or more protocol index IDs.- Parameters:
context (
ProtocolContext) – Context instance to register.name (
str|None) – Protocol index ID to register the context under; if not given,ProtocolContext.protocol()is used, which is the usual case.
- Raises:
RegistryError – If
contextis not aProtocolContext, or if a context is already registered for the same protocol.
- classmethod make(value)[source]¶
Coerce
valueinto aContextRegistry.This is the normalisation used by the public interfaces, so that a caller may pass whichever shape is most convenient:
None– an empty registry;a
ContextRegistry– copied as is;a single
ProtocolContext;a mapping of protocol index ID to
ProtocolContext;any iterable of
ProtocolContext.
- Parameters:
value (
ContextRegistry|ProtocolContext|Mapping[str,ProtocolContext] |Iterable[ProtocolContext] |None) – Value to coerce.- Return type:
Self- Returns:
A new
ContextRegistry.- Raises:
RegistryError – If
valueis of an unsupported type.
- match(names, cls=None)[source]¶
Find the context registered for any of
names.- Parameters:
- Return type:
- Returns:
The first matching context, or
Noneif there is none.
Type Variables¶
- pcapkit.corekit.context._CT: pcapkit.corekit.context.ProtocolContext¶