Parsing Context¶
Parsing Context¶
pcapkit.corekit.context provides a protocol keyed channel for
caller supplied information that a protocol needs in order to parse a
packet, but that is not carried on the wire.
Most protocols are self describing – every length, offset and type that
pcapkit needs to walk a packet is present in the packet itself. A
few are not. 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 be derived from the Security
Association (SA), which is negotiated out of band and is therefore
knowable 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. The registry is handed to
Extractor once, and is then
propagated down the protocol stack by
Protocol._import_next_layer,
so that a protocol nested arbitrarily deep can reach it through
Protocol._get_context.
Example
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 object frequently holds secrets – ESP encryption and
integrity keys, for instance. Contexts are therefore held as plain
instance attributes on the protocol object and are never written
into the protocol’s data model, which is the only thing that reaches
Info.to_dict and,
from there, the output dumpers. Implementations of
ProtocolContext 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.
- 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.- Return type:
- 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.