Fix silently-corrupt keys in `parse_wg_maddr()`
`_segments()` called `Multiaddr(maddr)` purely to validate, then
swallowed every failure under `except Exception: pass`. That was
harmless pre-#108 — w/o a `wg` codec there was nothing to
validate — but now that the codec is pinned in, the swallow is
load-bearing and disabled: a malformed key sails past validation
into `wg8_pubkey()`, which happily emits a corrupt b64 str, and
the returned struct then fails its own `.maddr` round-trip. No
raise, just quietly wrong output.
Deats,
- add `_have_wg_maddr_proto()`, the gate plan-03 already
referenced but which never actually existed. Impl'd as
`protocols.protocol_with_name('wg')` under
`except ProtocolNotFoundError` and cached in a mod global,
same shape as the TIPC plan's `is_tipc_available()`.
- only validate when that gate is `True`, and let
`StringParseError` propagate — a maddr which doesn't parse
must NOT reach `wg8_pubkey()`.
- keep the degraded split for a pre-#108 install, now w/ an
explicit `XXX` naming the validation you give up.
So parsing stays pure but becomes total-or-raises. Our own
`ValueError`s (missing `/wg/` seg, bare tunnel w/o an overlay
ep) are unaffected, as is the `wg(8)` b64 round-trip.
(this patch was generated in some part by `claude-code` using `claude-opus-5` (`anthropic`))
ng_tpts_planning
parent
cc85f17f5f
commit
7d6e79551e
|
|
@ -2,9 +2,9 @@
|
||||||
r'''
|
r'''
|
||||||
Parse `wg`-tunnelled multiaddrs into `tractor`-ready addrs.
|
Parse `wg`-tunnelled multiaddrs into `tractor`-ready addrs.
|
||||||
|
|
||||||
The canonical form (per py-multiaddr PR #108, verified to parse +
|
The canonical form (per py-multiaddr #108, verified to parse +
|
||||||
round-trip on that branch) nests the *overlay* endpoint **after**
|
round-trip against its upstream merge) nests the *overlay*
|
||||||
the `/wg/` segment:
|
endpoint **after** the `/wg/` segment:
|
||||||
|
|
||||||
/ip4/10.0.0.1/udp/51820/wg/u<key>/ip4/10.0.11.1/tcp/1616
|
/ip4/10.0.0.1/udp/51820/wg/u<key>/ip4/10.0.11.1/tcp/1616
|
||||||
\_______ wg bearer ______/\_ key _/\____ tractor ep _____/
|
\_______ wg bearer ______/\_ key _/\____ tractor ep _____/
|
||||||
|
|
@ -111,8 +111,10 @@ def parse_wg_maddr(
|
||||||
Split a `wg`-tunnelled maddr into its bearer/key/overlay
|
Split a `wg`-tunnelled maddr into its bearer/key/overlay
|
||||||
parts. Pure — no I/O.
|
parts. Pure — no I/O.
|
||||||
|
|
||||||
Uses `py-multiaddr` when it knows the `wg` proto (PR #108),
|
Total-or-raises: with a `wg`-aware `py-multiaddr` (#108) an
|
||||||
else falls back to a minimal segment split.
|
unparseable maddr raises instead of yielding a struct built
|
||||||
|
from garbage segments. See `_segments()` for the degraded
|
||||||
|
pre-#108 path.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
segs: list[str] = _segments(maddr)
|
segs: list[str] = _segments(maddr)
|
||||||
|
|
@ -164,22 +166,53 @@ def parse_wg_maddr(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _segments(maddr: str) -> list[str]:
|
_wg_proto_known: bool|None = None
|
||||||
|
|
||||||
|
|
||||||
|
def _have_wg_maddr_proto() -> bool:
|
||||||
'''
|
'''
|
||||||
Deliver a maddr's `/`-split segments, preferring the real
|
True iff the installed `py-multiaddr` knows the `/wg/` proto,
|
||||||
parser when it supports `wg`.
|
i.e. carries py-multiaddr#108.
|
||||||
|
|
||||||
|
Merged upstream 2026-07-28 but in no release as of `0.2.0`,
|
||||||
|
hence the `[tool.uv.sources]` `rev` pin.
|
||||||
|
|
||||||
|
Pure predicate; result cached since it can't change without a
|
||||||
|
reinstall.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from multiaddr import Multiaddr
|
global _wg_proto_known
|
||||||
try:
|
if _wg_proto_known is None:
|
||||||
# the real thing: validates every proto + value
|
from multiaddr.protocols import protocol_with_name
|
||||||
|
from multiaddr.exceptions import ProtocolNotFoundError
|
||||||
|
try:
|
||||||
|
protocol_with_name('wg')
|
||||||
|
_wg_proto_known = True
|
||||||
|
except ProtocolNotFoundError:
|
||||||
|
_wg_proto_known = False
|
||||||
|
|
||||||
|
return _wg_proto_known
|
||||||
|
|
||||||
|
|
||||||
|
def _segments(maddr: str) -> list[str]:
|
||||||
|
'''
|
||||||
|
Deliver a maddr's `/`-split segments, validating via the real
|
||||||
|
parser whenever it knows `wg`.
|
||||||
|
|
||||||
|
'''
|
||||||
|
if _have_wg_maddr_proto():
|
||||||
|
from multiaddr import Multiaddr
|
||||||
|
# the real thing: validates every proto + value, incl.
|
||||||
|
# that the `wg` key decodes to exactly 32 bytes. Let it
|
||||||
|
# raise — a maddr that doesn't parse must NOT reach
|
||||||
|
# `wg8_pubkey()`, which would happily emit a corrupt key.
|
||||||
Multiaddr(maddr)
|
Multiaddr(maddr)
|
||||||
except Exception:
|
|
||||||
# XXX STOPGAP, only until py-multiaddr#108 lands; then
|
# XXX, degraded path for a pre-#108 `py-multiaddr` ONLY: no
|
||||||
# this branch is dead and `Multiaddr` is authoritative.
|
# per-segment validation, so a malformed key survives to the
|
||||||
# We deliberately DON'T hand-roll a `wg` codec (the whole
|
# returned struct. We deliberately DON'T hand-roll a `wg`
|
||||||
# point of gh #429 was dropping the NIH parser).
|
# codec (the whole point of gh #429 was dropping the NIH
|
||||||
pass
|
# parser) — install the pinned rev to get validation back.
|
||||||
return [s for s in maddr.split('/') if s]
|
return [s for s in maddr.split('/') if s]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue