Skip to content

keep an established v3 authoritative engine ID - #651

Open
ityashag wants to merge 1 commit into
gosnmp:masterfrom
ityashag:fix/v3-keep-established-engine-id
Open

ityashag wants to merge 1 commit into
gosnmp:masterfrom
ityashag:fix/v3-keep-established-engine-id

Conversation

@ityashag

Copy link
Copy Markdown

Fixes #646 (item 4 of #601).

  1. storeSecurityParameters only adopts an authoritative engine ID while the session's is empty, which is initial discovery, including the usmStatsUnknownUserNames variant. once one is established, a different engine ID is refused with an error wrapping ErrUnknownEngineID, and the session keeps its engine ID, keys, boots and time.
  2. send() now returns as soon as storing fails. before, a usmStatsUnknownEngineIDs or notInTimeWindows Report from another engine had its parameters stored and the request was resent to the new engine. now it comes back as errors.Is(err, ErrUnknownEngineID) and is not returned as a successful result, so a caller like Telegraf (fix(inputs.snmp): Drop the connection to an agent after a failed gather influxdata/telegraf#19855) can decide to rediscover.
  3. in the receive loop, a non-Report response whose engine ID differs from the established one is discarded (RFC 3412 7.2 step 12), so it can't end the request early and the genuine response can still arrive.

the helper engineIDChanged holds the "established and different" check, so both places use the same rule. setSecurityParameters is unchanged because updatePktSecurityParameters also uses it to copy the session's engine ID into an outgoing packet.

this is a behavior change for agents that get a new engine ID on reboot, like the UniFi APs in #601. today the client follows the new ID silently; with this change those requests fail with ErrUnknownEngineID until the caller clears the engine ID and rediscovers. that's what the issue asks for, but flagging it in case you want it called out in the release notes.

tests are in a new v3_engineid_test.go on the #602 harness, with the agent answering as a different engine from the one the session established:

  • TestV3EngineIDNoAuthResponseKeepsIdentity: a noAuthNoPriv GetResponse from another engine.
  • TestV3EngineIDSignedResponseKeepsIdentity: a GetResponse signed with the user's key localized to another engine ID.
  • TestV3EngineIDChangedReportIsAnError: an authenticated usmStatsUnknownEngineIDs Report from another engine.

all three fail on master: the first two return the response and switch engine IDs, and the third resends to the new engine and succeeds. they pass with this change. the existing discovery and harness tests are untouched and pass.

  • make test and make test-race pass (Go 1.27.4, linux/arm64). make test-race: 413 passed / 29 skipped, against 410 / 29 on master.
  • golangci-lint v2.15.0 as CI runs it: 0 issues.

this is independent of #650 (#643). both touch the response checks in sendOneRequest, so whichever lands second needs a small rebase, which i'll do.

send() stored the security parameters of every accepted v3 result, and
setSecurityParameters replaced a differing authoritative engine ID and
relocalized the keys. So a noAuthNoPriv response from another engine, or an
authenticated one signed with the user's key localized to another engine ID,
moved an established session to that engine. Receive-side USM parsing
relocalizes the copied keys to the response's engine ID before the HMAC is
checked, so the second case verifies.

Only discovery, while the session's engine ID is empty, adopts one now.
storeSecurityParameters refuses a different engine ID with an error wrapping
ErrUnknownEngineID, and send() returns that error instead of resending after
the Report. A non-Report response from another engine is discarded in the
receive loop (RFC 3412 7.2 step 12), so it can't end the request.

Fixes gosnmp#646

Signed-off-by: Yash Agarwal <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve the established SNMPv3 authoritative engine identity

1 participant