a positive test proves Ze does what the requirement demands and a negative one proves it refuses what the requirement forbids
RFC 3579 - RADIUS (Remote Authentication Dial In User Service) Support For Extensible Authentication Protocol (EAP)
Every requirement this repository extracted from RFC 3579, the tests bound to it, and what a reader has verified about them. This summary is enrolled and gated by ./le rfc check.
Overview
Positive
what Ze has
the requirement admits no counter-case, so one polarity plus a recorded reason is the whole proof available for it
one direction is tested, the other is neither tested nor excused, and nothing states which
scoped tests exist; the remaining obligation is unmet or unproven, with zero whole-requirement credit
a red was observed once under a recorded procedure, and the unit, the claim and the producer it rested on still hash to what was recorded. The break is not re-run. A test pair is not a proof until one has been observed
Neutral
measures that are neither good news nor bad
MUST-level requirements the gate HOLDS. A population, not a result: the shares beside it are what says how Ze stands
an obligation that does not bind Ze. A {not-applicable} annotation says it never bound; a {feature-declined} annotation says its condition is an optional feature Ze does not offer, and quotes the RFC sentence that makes it optional. Scope, not coverage: it stays in the denominator every share on this page is taken over
a {not-applicable} annotation says the obligation does not bind Ze, so no test is owed for it. It stays in the denominator every share here is taken over
a {lower-layer} annotation says a layer under Ze performs the behavior, on state Ze installs into that layer, and names the producer that installs it. The obligation binds Ze and is met; Ze proves none of it, because its own boundary carries no value the behavior reads
a {feature-declined} annotation says the obligation is conditional on a feature the RFC makes optional and Ze does not offer, and it quotes the sentence that makes it optional. The condition is false, so nothing is owed and nothing is missing. It stays in the denominator every share here is taken over
Negative
what Ze owes
no test carries the requirement id, whether or not a gap states why
The 8 shares marked as a part above are the whole of the 31 gated MUSTs: they add to 100%. Proven by a recorded break is a share of TAGGED UNITS, a different population, so it is not one of them.
How to read the colors
A color names what the measure MEANS, not how well Ze scores on it. Green is a good outcome at any value, red is a bad one, and neither a population nor a scope count is an outcome, so both take no color. The number under the label is what says how far Ze has got.
| Card | Tone here | Why that color |
|---|---|---|
| Gated MUSTs | neutral | no color: a population is a scale, and a larger one is neither good news nor bad. It is the accounting total |
| Out of scope | neutral | no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim |
| Tested both ways | ok | green at every value: a test pair is the outcome this gate exists to produce, and the share under the label is what says how far Ze has got |
| One polarity plus reason | ok | green at every value: where no counter-case exists, one polarity IS the complete answer, and a recorded reason is what the gate demands beside it |
| One polarity, unexcused | ok | green at zero, RED above it: half a proof with no reason for the other half |
| Partial proof; remaining gap | ok | green at zero, RED above it: a tested clause cannot prove the whole requirement |
| No test at all | bad | green at zero, RED above it: a binding obligation nothing exercises is a claim with nothing behind it, whether or not a reason is stated |
| Not applicable | neutral | no color: an obligation that never bound Ze is neither an achievement nor a failure, and counting it either way would be a claim |
| Met below Ze | neutral | no color: an obligation met below Ze is neither a test Ze wrote nor work Ze owes, and the two green shares above are what says how much Ze proves itself |
| Optional feature declined | neutral | no color: an obligation whose condition Ze never meets is neither an achievement nor a failure. The absent FEATURE is disclosed on the RFC's own status row, as an implementation gap a later scope decision can revisit |
| Proven by a recorded break | ok | green at every value: an observed break is the outcome the discrimination gate exists to produce. The denominator is TAGGED UNITS, not obligations, so this share is not one of the parts above |
| Audit verdicts | warn | RED on the first weak, wrong or unimplemented verdict, amber while a verdict is no longer current or a gated MUST is unjudged, green when every one is judged sound and current |
At a glance
| Field | Value |
|---|---|
| Public status | Partial |
| Enrolment | Enrolled |
| Requirements | 50 |
| Gated MUST-level | 31 |
| Not applicable, so out of scope | 0 |
| Declared gaps | 14 |
| Declared gaps a test demonstrates | 0 |
| Gated with no test | 0 |
| Nightly-only evidence | 0 |
| Test tags | 47 |
| Tagged units | 47 |
| Recorded audit verdicts | 18 |
| Discrimination records | 47 |
| Summary | rfc/short/rfc3579.md |
| Requirement shard | rfc/requirements/rfc3579.md |
| RFC text | rfc/full/rfc3579.txt |
Enrolment
Enrolled: RADIUS/EAP, ze in the NAS (RADIUS client) role: 31 MUST-level requirements. Ze runs the conversation this document describes, for operator login. `internal/component/radius/dict.go` declares EAP-Message at 79, `SignMessageAuthenticator` (`internal/component/radius/packet.go`) signs every EAP-bearing Access-Request beside the two verifiers that were there first, and `authenticateEAP` (`internal/component/radius/authenticator_eap.go`) answers each Access-Challenge instead of rejecting it. The obligations addressed to the RADIUS authentication server, to a RADIUS proxy and to a security server are excluded in `rfc/extraction/rfc3579.json` as `binds-another-role`: ze binds an ephemeral UDP socket in `NewClient` and `(*Client).readLoop` dispatches a datagram only against a waiter `(*Client).Exchange` registered for its own outstanding request, so no Access-Request receive path exists anywhere in the tree.
What the public ledger says
Status: Partial
What the ledger says is covered
Ze is the NAS and runs the RADIUS/EAP conversation for operator login, withauth-method eap-md5 or eap-mschapv2. It encapsulates one EAP packet per RADIUS packet in consecutive EAP-Message attributes split at 253 octets (appendEAPMessage, eapPacketFrom, internal/component/radius/eap.go), signs every EAP-bearing Access-Request (SignMessageAuthenticator, internal/component/radius/packet.go), silently discards a reply whose Message-Authenticator does not verify ((*Client).dispatchResponse, internal/component/radius/client.go), and answers each Access-Challenge with the peer's EAP-Response and the challenge's State unmodified (authenticateEAP, internal/component/radius/authenticator_eap.go). It copies the peer's own EAP-Response/Identity Type-Data into User-Name on every request of the conversation, validates each server EAP header before the peer sees it, processes the EAP-Message attributes before it reads the reply code, and never offers a password credential in place of the configured EAP method. Ze answers EAP itself, as the peer, rather than passing frames through.
What the ledger says remains
Fourteen MUST requirements are unproven, unreached or unmet, none of which changes what an operator can configure. The EAP-bearing Access-Requests ze sends are the admin login's, built by(*radiusAuthenticator).exchange (internal/component/radius/authenticator.go), and each carries NAS-Port-Id naming the access channel the login arrived on, taken from the login's AuthRequest.Service: ssh for an SSH login and web for a web login (RFC3579-3-2); the L2TP subscriber Access-Request, which carries no EAP-Message, sends NAS-Port as the L2TP session id (buildAuthAttrs, internal/component/l2tp/plugins/authradius/handler.go). The pass-through architecture accounts for most: ze answers EAP for the operator and forwards no EAP frame, so Section 2.1's EAP-Start and the Nak relay have no path, and the Section 2.2 Error-Cause 202 branch cannot fire because ze holds no queue of EAP-Responses for its antecedent to match. Four prohibitions hold by construction and are tagged by nothing, because a test would have to observe a packet no code path can build: Sections 2.1, 2.6.3 and 2.6.5. EAP-TLS is implemented in the peer (internal/core/eap) and not offered by auth-method, which needs an operator certificate and key. Ze's PPP NAS never negotiates EAP, so the Section 4.3.6 obligations that bind a NAS whose peers require EAP are unreached. The IPsec-for-RADIUS profile of Section 4.2 is absent: ze offers no way to run RADIUS over an IPsec SA and no zero-length shared secret. Section 4.3.4's ban on sharing a secret between an EAP NAS and a User-Password NAS is not checked at config load.
Coverage
| Bucket | Count | What it counts |
|---|---|---|
| Positive and negative tests | 17 | one part of the gated population |
| Annotated (including scoped evidence) | 14 | one part of the gated population |
| One polarity only | 0 | one part of the gated population |
| No test and no annotation | 0 | one part of the gated population |
| Partial proof; remaining gap (subset of annotated; zero whole-requirement credit) | 0 | an overlay: each of these is also counted by the part it falls in |
| Evidence that runs nightly only | 0 | an overlay: each of these is also counted by the part it falls in |
| Derived from other rows | 0 | outside the gated population: each asserts nothing and derives its state from the rows it names, which the parts above already count |
| Gated MUST-level requirements | 31 | every gated MUST falls in exactly one bucket above |
Positive and negative tests (17): RFC3579-1-1, RFC3579-1.2-1, RFC3579-2.1-1, RFC3579-2.1-3, RFC3579-2.2-1, RFC3579-2.6.3-1, RFC3579-2.6.3-2, RFC3579-2.6.4-1, RFC3579-3-1, RFC3579-3.1-1, RFC3579-3.1-2, RFC3579-3.1-3, RFC3579-3.1-4, RFC3579-3.2-1, RFC3579-3.3-1, RFC3579-3.3-2, RFC3579-4.3.6-2
Annotated (including scoped evidence) (14): RFC3579-1-2, RFC3579-1.2-2, RFC3579-2.1-2, RFC3579-2.2-2, RFC3579-2.6.3-3, RFC3579-2.6.5-1, RFC3579-4.2-1, RFC3579-4.2-2, RFC3579-4.2-3, RFC3579-4.3.4-1, RFC3579-4.3.6-1, RFC3579-4.3.6-3, RFC3579-4.3.6-4, RFC3579-4.3.6-5
Requirements
| Requirement | Level | Section | Tests |
|---|---|---|---|
RFC3579-1-1 | This implies that a NAS that is unable to offer EAP service MUST NOT implement the RADIUS attributes for EAP. (§1) | ||
| MUST NOT | 1 - Introduction | ||
RFC3579-1-2 | A NAS MUST treat a RADIUS Access-Accept requesting an unavailable service as an Access-Reject instead. (§1) | ||
| MUST | 1 - Introduction | positive
no testno positive testnegative
no testno negative test{gap}: `(*radiusAuthenticator).result` rejects an Access-Accept whose Service-Type is not Login-User (`AcceptedServiceType`, internal/component/radius/attr.go), which is the RFC 2865 form of this rule and covers the EAP path too, because authenticateEAP returns through that same function. What stays untested is this document's own form of the rule, an Accept concluding an EAP conversation ze could not run: `parseAuthMethod` refuses an unknown auth-method at config load, so ze only ever runs a method it offers and the branch has no input |
|
RFC3579-1.2-1 | This is interpreted to be a human readable string of characters, and MUST NOT affect operation of the protocol. (§1.2) | ||
| MUST NOT | 1.2 - Terminology | ||
RFC3579-1.2-2 | The message encoding MUST follow the UTF-8 transformation format [RFC2279]. (§1.2) | ||
| MUST | 1.2 - Terminology | positive
no testno positive testnegative
no testno negative test{gap}: ze now DECODES a displayable message -- `(*PeerSession).notificationResponse` (internal/core/eap/peer.go) carries the Type-2 Request's text out and `processEAPMessage` (internal/component/radius/authenticator_eap.go) logs it -- and encodes none. This sentence binds whoever encodes the message, and ze writes no Reply-Message and sends no Notification Request, so nothing here chooses an encoding to assert |
|
RFC3579-2.1-1 | Reception of a RADIUS Access-Reject packet MUST result in the NAS denying access to the authenticating peer. (§2.1, restated later in §2.1) | ||
| MUST | 2.1 - Protocol Overview | ||
RFC3579-2.1-2 | The NAS MUST NOT "manufacture" a Success or Failure packet as the result of a timeout. (§2.1) | ||
| MUST NOT | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test{gap}: every EAP packet ze puts on the RADIUS wire came out of `(*eap.PeerSession).Process` (internal/core/eap/peer.go), and a timeout returns an error from `(*Client).SendToServers` that `authenticateEAP` passes up, so no branch manufactures a Success or Failure. Nothing tags the prohibition, because a test would have to observe a packet no code path can build |
|
RFC3579-2.1-3 | In order to permit non-EAP aware RADIUS proxies to forward the Access-Request packet, if the NAS initially sends an EAP-Request/Identity message to the peer, the NAS MUST copy the contents of the Type-Data field of the EAP-Response/Identity received from the peer into the User-Name attribute and MUST include the Type-Data field of the EAP-Response/Identity in the User-Name attribute in every subsequent Access-Request. (§2.1) | ||
| MUST | 2.1 - Protocol Overview | ||
RFC3579-2.2-1 | While acting as a pass-through, the NAS MUST validate the EAP header fields (Code, Identifier, Length) prior to forwarding an EAP packet to or from the RADIUS server. (§2.2) | ||
| MUST | 2.2 - Invalid Packets | ||
RFC3579-2.2-2 | If so, a new EAP-Response packet, if available, MUST be sent to the RADIUS server within an Access-Request, and the EAP-Message attribute(s) included within the Access-Challenge are silently discarded. (§2.2) | ||
| MUST | 2.2 - Invalid Packets | positive
no testno positive testnegative
no testno negative test{gap}: ze reads no Error-Cause attribute, so an Access-Challenge carrying 202 is answered like any other. The MUST is conditional -- "If so" refers to additional EAP-Response packets received matching the current Identifier -- and ze holds no such queue: it is its own peer, and `(*eap.PeerSession).Process` (internal/core/eap/peer.go) returns exactly one Response per Request. So the antecedent never holds and there is no second Response to send |
|
RFC3579-2.6.3-1 | The NAS MUST make its access control decision based solely on the RADIUS Packet Type (Access-Accept/Access-Reject). (§2.6.3) | ||
| MUST | 2.6.3 - Conflicting Messages | ||
RFC3579-2.6.3-2 | The access control decision MUST NOT be based on the contents of the EAP packet encapsulated in one or more EAP-Message attributes, if present. (§2.6.3) | ||
| MUST NOT | 2.6.3 - Conflicting Messages | ||
RFC3579-2.6.3-3 | Since the responsibility for avoiding conflicts lies with the RADIUS server, the NAS MUST NOT "manufacture" EAP packets in order to correct contradictory messages that it receives. (§2.6.3) | ||
| MUST NOT | 2.6.3 - Conflicting Messages | positive
no testno positive testnegative
no testno negative test{gap}: `authenticateEAP` (internal/component/radius/authenticator_eap.go) sends only what `(*eap.PeerSession).Process` returned, and on a contradictory reply it logs the peer's objection and drops it rather than correcting it. Nothing tags the prohibition, because a test would have to observe a manufactured packet no code path can build |
|
RFC3579-2.6.4-1 | In order to ensure the correct processing of RADIUS packets, the NAS MUST first process the attributes, including the EAP-Message attribute(s), prior to processing the Accept/Reject indication. (§2.6.4) | ||
| MUST | 2.6.4 - Priority | ||
RFC3579-2.6.5-1 | Reply-Message attribute(s) MUST NOT be included in any RADIUS message containing an EAP-Message attribute. (§2.6.5) | ||
| MUST NOT | 2.6.5 - Displayable Messages | positive
no testno positive testnegative
no testno negative test{gap}: `eapCredential` (internal/component/radius/authenticator_eap.go) builds an EAP-bearing Access-Request from the EAP-Message run, the Message-Authenticator and the server's State, and appends no Reply-Message; `exchange` adds Service-Type, NAS-Identifier, User-Name and NAS-IP-Address, none of them Reply-Message. The exclusion holds by construction and no test tags it |
|
RFC3579-3-1 | either NAS-Identifier, NAS-IP-Address or NAS-IPv6-Address attributes MUST be included. (§3) | ||
| MUST | 3 - Attributes | ||
RFC3579-3.1-1 | If multiple EAP-Message attributes are contained within an Access-Request or Access-Challenge packet, they MUST be in order and they MUST be consecutive attributes in the Access-Request or Access-Challenge packet. (§3.1) | ||
| MUST | 3.1 - EAP-Message | ||
RFC3579-3.1-2 | Multiple EAP packets MUST NOT be encoded within EAP-Message attributes contained within a single Access-Challenge, Access-Accept, Access-Reject or Access-Request packet. (§3.1) | ||
| MUST NOT | 3.1 - EAP-Message | ||
RFC3579-3.1-3 | Therefore the Message-Authenticator attribute MUST be used to protect all Access-Request, Access-Challenge, Access-Accept, and Access-Reject packets containing an EAP-Message attribute. (§3.1, restated §3.2, §3.3 Note 1 and §4.3.2) | ||
| MUST | 3.1 - EAP-Message | ||
RFC3579-3.1-4 | A NAS supporting the EAP-Message attribute MUST calculate the correct value of the Message-Authenticator and MUST silently discard the packet if it does not match the value sent. (§3.1, restated for any RADIUS client receiving an Access-Accept, Access-Reject or Access-Challenge at §3.2) | ||
| MUST | 3.1 - EAP-Message | ||
RFC3579-3.2-1 | When present in an Access-Request packet, Message-Authenticator is an HMAC-MD5 [RFC2104] hash of the entire Access-Request packet, including Type, ID, Length and Authenticator, using the shared secret as the key, as follows. Message-Authenticator = HMAC-MD5 (Type, Identifier, Length, Request Authenticator, Attributes) When the message integrity check is calculated the signature string should be considered to be sixteen octets of zero. (§3.2) | ||
| MUST | 3.2 - Message-Authenticator | ||
RFC3579-3.3-1 | The EAP-Message and Message-Authenticator attributes specified in this document MUST NOT be present in an Accounting-Request. (§3.3) | ||
| MUST NOT | 3.3 - Table of Attributes | ||
RFC3579-3.3-2 | An Access-Request that contains either a User-Password or CHAP-Password or ARAP-Password or one or more EAP-Message attributes MUST NOT contain more than one type of those four attributes. (§3.3 Note 1) | ||
| MUST NOT | 3.3 - Table of Attributes | ||
RFC3579-4.2-1 | Where RADIUS is run over IPsec ESP with a non-null transform, the secret shared between the NAS and the RADIUS server MAY NOT be configured. In this case, a shared secret of zero length MUST be assumed. (§4.2) | ||
| MUST | 4.2 - Security Protocol | positive
no testno positive testnegative
no testno negative test{gap}: ze offers no way to run RADIUS over an IPsec SA and its RADIUS server configuration always carries a secret (`internal/component/radius/config.go`), so the zero-length case is unreachable; spec-radius-admin-eap does not add it |
|
RFC3579-4.2-2 | When IPsec ESP is used with RADIUS, per-packet authentication, integrity and replay protection MUST be used. 3DES-CBC MUST be supported as an encryption transform (§4.2) | ||
| MUST | 4.2 - Security Protocol | positive
no testno positive testnegative
no testno negative test{gap}: ze has no RADIUS-over-IPsec profile, so nothing selects a transform for RADIUS traffic; spec-radius-admin-eap does not add it |
|
RFC3579-4.2-3 | HMAC-SHA1-96 MUST be supported as an authentication transform. (§4.2) | ||
| MUST | 4.2 - Security Protocol | positive
no testno positive testnegative
no testno negative test{gap}: same absent RADIUS-over-IPsec profile; ze negotiates no IPsec SA for RADIUS traffic; spec-radius-admin-eap does not add it |
|
RFC3579-4.3.4-1 | Where RADIUS shared secrets are configured, the RADIUS shared secret used by a NAS supporting EAP MUST NOT be reused by a NAS utilizing the User-Password attribute, since improper shared secret hygiene could lead to compromise of hidden attributes. (§4.3.4) | ||
| MUST NOT | 4.3.4 - Known Plaintext Attacks | positive
no testno positive testnegative
no testno negative test{gap}: ze holds both the admin backend's secret and the subscriber backend's secret and compares neither, so a configuration reusing one secret across an EAP NAS and a PAP NAS is accepted in silence; spec-radius-admin-eap |
|
RFC3579-4.3.6-1 | Should the NAS not be able to negotiate EAP, or should the EAP-Request sent by the NAS be of a different EAP type than what is expected, the authenticating peer MUST disconnect. (§4.3.6) | ||
| MUST | 4.3.6 - Negotiation Attacks | positive
no testno positive testnegative
no testno negative test{gap}: `(*eap.PeerSession).Process` (internal/core/eap/peer.go) NAKs toward its one configured method rather than answering a Request of another type, and a server that insists ends the exchange with an error that `authenticateEAP` returns, which ends the login. What is untested is that ending read as this section's disconnect |
|
RFC3579-4.3.6-2 | An authenticating peer expecting EAP to be negotiated for a session MUST NOT negotiate a weaker method, such as CHAP or PAP. (§4.3.6) | ||
| MUST NOT | 4.3.6 - Negotiation Attacks | ||
RFC3579-4.3.6-3 | In such cases, if any peers of the NAS MUST do EAP, then the NAS MUST attempt to negotiate EAP for every session. (§4.3.6) | ||
| MUST | 4.3.6 - Negotiation Attacks | positive
no testno positive testnegative
no testno negative test{gap}: ze's PPP NAS offers PAP, CHAP-MD5 and MS-CHAPv2 and never EAP (`internal/component/l2tp/ppp`), so it cannot attempt to negotiate EAP for any session; spec-radius-admin-eap |
|
RFC3579-4.3.6-4 | The authenticating peer MUST refuse to renegotiate authentication, even if the renegotiation is from CHAP to EAP. (§4.3.6, restated in the same section for an EAP-capable peer) | ||
| MUST | 4.3.6 - Negotiation Attacks | positive
no testno positive testnegative
no testno negative test{gap}: ze's admin login has no renegotiation path, and its PPP NAS never negotiates EAP, so nothing refuses a renegotiation; spec-radius-admin-eap |
|
RFC3579-4.3.6-5 | If EAP is negotiated but is not supported by the RADIUS proxy or server, then the server or proxy MUST respond with an Access-Reject. In these cases, a PPP NAS MUST send an LCP-Terminate and disconnect the peer. (§4.3.6) | ||
| MUST | 4.3.6 - Negotiation Attacks | positive
no testno positive testnegative
no testno negative test{gap}: ze's PPP NAS never negotiates EAP, so the branch that would send LCP-Terminate on an EAP-incapable server does not exist; spec-radius-admin-eap |
|
RFC3579-1.2-3 | The implementation SHOULD provide the capability of logging the error, including the contents of the silently discarded packet, and SHOULD record the event in a statistics counter. (§1.2) | ||
| SHOULD | 1.2 - Terminology | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-4 | Once EAP has been negotiated, the NAS SHOULD send an initial EAP-Request message to the authenticating peer. (§2.1) | ||
| SHOULD | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-7 | After a suitable number of timeouts have elapsed, the NAS SHOULD instead end the EAP conversation. (§2.1) | ||
| SHOULD | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-8 | Where the initial EAP-Request sent by the NAS is for an authentication Type (4 or greater), the peer MAY respond with a Nak indicating that it would prefer another authentication method that is not implemented locally. In this case, the NAS SHOULD send Access-Request encapsulating the received EAP-Response/Nak. (§2.1) | ||
| SHOULD | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-9 | If the NAS initially sends an EAP-Request for an authentication method, and the peer identity cannot be determined from the EAP-Response, then the User-Name attribute SHOULD be determined by another means. (§2.1) | ||
| SHOULD | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-11 | Since this technique can result in a large number of uncompleted RADIUS conversations, in situations where EAP unaware peers are common, or where peer support for EAP cannot be determined on initial contact (e.g. [IEEE8021X] Supplicants not initiating the conversation with an EAPOL-Start) it SHOULD NOT be employed by default. (§2.1) | ||
| SHOULD NOT | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.2-3 | A NAS compliant with this specification, on receiving an Access-Challenge with an Error-Cause attribute of value 202 (decimal) SHOULD discard the EAP-Response packet most recently transmitted to the RADIUS server and check whether additional EAP-Response packets have been received matching the current Identifier value. (§2.2) | ||
| SHOULD | 2.2 - Invalid Packets | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.6.5-2 | To avoid these problems, a NAS receiving a Reply-Message attribute from the RADIUS server SHOULD silently discard the attribute, rather than attempting to translate it to an EAP Notification Request. (§2.6.5) | ||
| SHOULD | 2.6.5 - Displayable Messages | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-3-2 | The NAS-Port or NAS-Port-Id attributes SHOULD be included by the NAS in Access-Request packets (§3) | ||
| SHOULD | 3 - Attributes | ||
RFC3579-3.1-5 | When RADIUS is used to enable EAP authentication, Access-Request, Access-Challenge, Access-Accept, and Access-Reject packets SHOULD contain one or more EAP-Message attributes. (§3.1) | ||
| SHOULD | 3.1 - EAP-Message | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-3.1-6 | Access-Challenge, Access-Accept, or Access-Reject packets including EAP-Message attribute(s) without a Message-Authenticator attribute SHOULD be silently discarded by the NAS. (§3.1) | ||
| SHOULD | 3.1 - EAP-Message | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-4.2-4 | To address the security vulnerabilities of RADIUS/EAP, implementations of this specification SHOULD support IPsec [RFC2401] along with IKE [RFC2409] for key management. IPsec ESP [RFC2406] with non-null transform SHOULD be supported, and IPsec ESP with a non-null encryption transform and authentication support SHOULD be used to provide per-packet confidentiality, authentication, integrity and replay protection. (§4.2) | ||
| SHOULD | 4.2 - Security Protocol | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-4.2-5 | AES-CBC SHOULD be supported. AES-CBC SHOULD be offered as a preferred encryption transform if supported. HMAC-SHA1-96 MUST be supported as an authentication transform. DES-CBC SHOULD NOT be used as the encryption transform. (§4.2) | ||
| SHOULD | 4.2 - Security Protocol | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-4.3.2-1 | As a result, the Message-Authenticator attribute SHOULD be used in Access-Request packets that do not have a User-Password attribute, in order to establish the identity of the NAS sending the request. (§4.3.2) | ||
| SHOULD | 4.3.2 - Spoofing and Hijacking | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2-1 | A NAS MAY authenticate local peers while at the same time acting as a pass-through for non-local peers and authentication methods it does not implement locally. (§2) | ||
| MAY | 2 - RADIUS Support for EAP | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-5 | A NAS MAY be configured to initiate with a default authentication method. (§2.1) | ||
| MAY | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-6 | Alternatively, the NAS MAY act as a pass-through, encapsulating the EAP-Response within EAP-Message attribute(s) sent to the RADIUS server within a RADIUS Access-Request packet. (§2.1) | ||
| MAY | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-2.1-10 | Rather than sending an initial EAP-Request packet to the authenticating peer, on detecting the presence of the peer, the NAS MAY send an Access-Request packet to the RADIUS server containing an EAP-Message attribute signifying EAP-Start. (§2.1) | ||
| MAY | 2.1 - Protocol Overview | positive
no testno positive testnegative
no testno negative test |
|
RFC3579-3.2-2 | This attribute MAY be used to authenticate and integrity-protect Access-Requests in order to prevent spoofing. It MAY be used in any Access-Request. (§3.2) | ||
| MAY | 3.2 - Message-Authenticator | positive
no testno positive testnegative
no testno negative test |
|
Gaps and untested MUSTs
| Requirement | State | Reason |
|---|---|---|
RFC3579-1-2 A NAS MUST treat a RADIUS Access-Accept requesting an unavailable service as an Access-Reject instead. (§1) |
{gap}, no test | `(*radiusAuthenticator).result` rejects an Access-Accept whose Service-Type is not Login-User (`AcceptedServiceType`, internal/component/radius/attr.go), which is the RFC 2865 form of this rule and covers the EAP path too, because authenticateEAP returns through that same function. What stays untested is this document's own form of the rule, an Accept concluding an EAP conversation ze could not run: `parseAuthMethod` refuses an unknown auth-method at config load, so ze only ever runs a method it offers and the branch has no input |
RFC3579-1.2-2 The message encoding MUST follow the UTF-8 transformation format [RFC2279]. (§1.2) |
{gap}, no test | ze now DECODES a displayable message -- `(*PeerSession).notificationResponse` (internal/core/eap/peer.go) carries the Type-2 Request's text out and `processEAPMessage` (internal/component/radius/authenticator_eap.go) logs it -- and encodes none. This sentence binds whoever encodes the message, and ze writes no Reply-Message and sends no Notification Request, so nothing here chooses an encoding to assert |
RFC3579-2.1-2 The NAS MUST NOT "manufacture" a Success or Failure packet as the result of a timeout. (§2.1) |
{gap}, no test | every EAP packet ze puts on the RADIUS wire came out of `(*eap.PeerSession).Process` (internal/core/eap/peer.go), and a timeout returns an error from `(*Client).SendToServers` that `authenticateEAP` passes up, so no branch manufactures a Success or Failure. Nothing tags the prohibition, because a test would have to observe a packet no code path can build |
RFC3579-2.2-2 If so, a new EAP-Response packet, if available, MUST be sent to the RADIUS server within an Access-Request, and the EAP-Message attribute(s) included within the Access-Challenge are silently discarded. (§2.2) |
{gap}, no test | ze reads no Error-Cause attribute, so an Access-Challenge carrying 202 is answered like any other. The MUST is conditional -- "If so" refers to additional EAP-Response packets received matching the current Identifier -- and ze holds no such queue: it is its own peer, and `(*eap.PeerSession).Process` (internal/core/eap/peer.go) returns exactly one Response per Request. So the antecedent never holds and there is no second Response to send |
RFC3579-2.6.3-3 Since the responsibility for avoiding conflicts lies with the RADIUS server, the NAS MUST NOT "manufacture" EAP packets in order to correct contradictory messages that it receives. (§2.6.3) |
{gap}, no test | `authenticateEAP` (internal/component/radius/authenticator_eap.go) sends only what `(*eap.PeerSession).Process` returned, and on a contradictory reply it logs the peer's objection and drops it rather than correcting it. Nothing tags the prohibition, because a test would have to observe a manufactured packet no code path can build |
RFC3579-2.6.5-1 Reply-Message attribute(s) MUST NOT be included in any RADIUS message containing an EAP-Message attribute. (§2.6.5) |
{gap}, no test | `eapCredential` (internal/component/radius/authenticator_eap.go) builds an EAP-bearing Access-Request from the EAP-Message run, the Message-Authenticator and the server's State, and appends no Reply-Message; `exchange` adds Service-Type, NAS-Identifier, User-Name and NAS-IP-Address, none of them Reply-Message. The exclusion holds by construction and no test tags it |
RFC3579-4.2-1 Where RADIUS is run over IPsec ESP with a non-null transform, the secret shared between the NAS and the RADIUS server MAY NOT be configured. In this case, a shared secret of zero length MUST be assumed. (§4.2) |
{gap}, no test | ze offers no way to run RADIUS over an IPsec SA and its RADIUS server configuration always carries a secret (`internal/component/radius/config.go`), so the zero-length case is unreachable; spec-radius-admin-eap does not add it |
RFC3579-4.2-2 When IPsec ESP is used with RADIUS, per-packet authentication, integrity and replay protection MUST be used. 3DES-CBC MUST be supported as an encryption transform (§4.2) |
{gap}, no test | ze has no RADIUS-over-IPsec profile, so nothing selects a transform for RADIUS traffic; spec-radius-admin-eap does not add it |
RFC3579-4.2-3 HMAC-SHA1-96 MUST be supported as an authentication transform. (§4.2) |
{gap}, no test | same absent RADIUS-over-IPsec profile; ze negotiates no IPsec SA for RADIUS traffic; spec-radius-admin-eap does not add it |
RFC3579-4.3.4-1 Where RADIUS shared secrets are configured, the RADIUS shared secret used by a NAS supporting EAP MUST NOT be reused by a NAS utilizing the User-Password attribute, since improper shared secret hygiene could lead to compromise of hidden attributes. (§4.3.4) |
{gap}, no test | ze holds both the admin backend's secret and the subscriber backend's secret and compares neither, so a configuration reusing one secret across an EAP NAS and a PAP NAS is accepted in silence; spec-radius-admin-eap |
RFC3579-4.3.6-1 Should the NAS not be able to negotiate EAP, or should the EAP-Request sent by the NAS be of a different EAP type than what is expected, the authenticating peer MUST disconnect. (§4.3.6) |
{gap}, no test | `(*eap.PeerSession).Process` (internal/core/eap/peer.go) NAKs toward its one configured method rather than answering a Request of another type, and a server that insists ends the exchange with an error that `authenticateEAP` returns, which ends the login. What is untested is that ending read as this section's disconnect |
RFC3579-4.3.6-3 In such cases, if any peers of the NAS MUST do EAP, then the NAS MUST attempt to negotiate EAP for every session. (§4.3.6) |
{gap}, no test | ze's PPP NAS offers PAP, CHAP-MD5 and MS-CHAPv2 and never EAP (`internal/component/l2tp/ppp`), so it cannot attempt to negotiate EAP for any session; spec-radius-admin-eap |
RFC3579-4.3.6-4 The authenticating peer MUST refuse to renegotiate authentication, even if the renegotiation is from CHAP to EAP. (§4.3.6, restated in the same section for an EAP-capable peer) |
{gap}, no test | ze's admin login has no renegotiation path, and its PPP NAS never negotiates EAP, so nothing refuses a renegotiation; spec-radius-admin-eap |
RFC3579-4.3.6-5 If EAP is negotiated but is not supported by the RADIUS proxy or server, then the server or proxy MUST respond with an Access-Reject. In these cases, a PPP NAS MUST send an LCP-Terminate and disconnect the peer. (§4.3.6) |
{gap}, no test | ze's PPP NAS never negotiates EAP, so the branch that would send LCP-Terminate on an EAP-incapable server does not exist; spec-radius-admin-eap |
Proof state
A tagged unit reads unproven where no discrimination record exists for it: nothing in this tree has been observed to break it, so the claim its tag makes is unproven.
RFC3579-1-1
This implies that a NAS that is unable to offer EAP service MUST NOT implement the RADIUS attributes for EAP. (§1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. + TestRFC3579EAPAttributesServeALiveEAPMethod: the NAS that implements EAP-Message offers EAP (admin login, auth-method eap-mschapv2 completes, every Access-Request carries EAP-Message; red when authenticateEAP is disabled). - TestRFC3579SubscriberNASRefusesEAPMessage: the L2TP subscriber NAS, which offers PPP peers no EAP, answers CoA-Request and Disconnect-Request carrying EAP-Message with NAK Error-Cause 401, no event, no teardown; adding EAP-Message to coaSupportedAttrs/disconnectSupportedAttrs turns it red (recorded at coa.go unsupportedAttr). The older dictionary units stay as declaration-only supplementary tags.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC3579SubscriberNASRefusesEAPMessage |
unit/verify | revert, verified |
| negative | TestRFC2869DictionaryDeclaresNoAttributeForAnUnofferedService |
unit/verify | no-break escape (declaration-only), which is not a proof, verified |
| positive | TestRFC2869DictionaryCoversTheServicesZeOffers |
unit/verify | no-break escape (declaration-only), which is not a proof, verified |
| positive | TestRFC3579EAPAttributesServeALiveEAPMethod |
unit/verify | revert, verified |
RFC3579-1-2
A NAS MUST treat a RADIUS Access-Accept requesting an unavailable service as an Access-Reject instead. (§1)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-1-2, so no unit is bound to it.
RFC3579-1.2-1
This is interpreted to be a human readable string of characters, and MUST NOT affect operation of the protocol. (§1.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. negative compares verdict, profiles and source with and without a Notification carrying text; positive shows the message is delivered (logged, Notification Response sent) and not acted on
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapNotificationDoesNotSteerTheLogin |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapNotificationIsAnsweredAndLogged |
unit/verify | revert, verified |
RFC3579-1.2-2
The message encoding MUST follow the UTF-8 transformation format [RFC2279]. (§1.2)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-1.2-2, so no unit is bound to it.
RFC3579-2.1-1
Reception of a RADIUS Access-Reject packet MUST result in the NAS denying access to the authenticating peer. (§2.1, restated later in §2.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Access-Reject returns aaa.ErrAuthRejected with no profiles; the negative carries an EAP-Success inside the Access-Reject and still denies
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapAccessRejectDeniesEvenCarryingEAPSuccess |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAccessRejectDeniesAccess |
unit/verify | revert, verified |
RFC3579-2.1-2
The NAS MUST NOT "manufacture" a Success or Failure packet as the result of a timeout. (§2.1)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-2.1-2, so no unit is bound to it.
RFC3579-2.1-3
In order to permit non-EAP aware RADIUS proxies to forward the Access-Request packet, if the NAS initially sends an EAP-Request/Identity message to the peer, the NAS MUST copy the contents of the Type-Data field of the EAP-Response/Identity received from the peer into the User-Name attribute and MUST include the Type-Data field of the EAP-Response/Identity in the User-Name attribute in every subsequent Access-Request. (§2.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. positive compares User-Name to the Type-Data of the peer's EAP-Response/Identity read off the wire; negative checks every subsequent request (method Responses, not Identity) carries the same User-Name. Both clauses covered
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapUserNameRidesEverySubsequentRequest |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapUserNameIsThePeerIdentity |
unit/verify | revert, verified |
RFC3579-2.2-1
While acting as a pass-through, the NAS MUST validate the EAP header fields (Code, Identifier, Length) prior to forwarding an EAP packet to or from the RADIUS server. (§2.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Judge 2026-09-30 (cont 5). The prior weak (Code and Identifier unproven) is closed and was a real defect: an Access-Challenge carrying EAP Code 0 was handed to the peer and answered. Fix in processEAPMessage pins Code 1 for an Access-Challenge only (Accept/Reject may carry Success/Failure), and new checkEAPResponseHeader requires Code 2 and the current Request's Identifier before forwarding; RFC 3579 Section 2.2 quotes above both, text checked. Length: the existing corruptEAPFrom pair. Code, server side: negative TestRFC3579NASRefusesANonRequestCodeInAChallenge rewrites only the Code octet (0,2,3,4,5,255) and asserts the infrastructure error naming the server's EAP header, not ErrAuthRejected, and exactly one Access-Request (nothing forwarded). Code+Identifier, peer side: positive TestRFC3579NASForwardsTheCurrentIdentifierBothWays pairs every Challenge's Request with the next Access-Request's Response (Code 2, same Identifier) over a full EAP-MSCHAPv2 login and the check admits a matching pair; negative TestRFC3579NASRefusesAResponseOffTheCurrentIdentifier drives checkEAPResponseHeader directly (Identifier 6/8 vs 7, Code 1, Code 4), since the in-process peer echoes the Identifier and cannot be driven off it. Ze ends the login on a mismatched Response rather than silently discarding it; with an in-process peer no other Response can arrive, so nothing is forwarded either way. Valid EAP-TLS/MSCHAPv2 flows stay green (race run 2026-09-30). All units recorded red.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRFC3579NASRefusesANonRequestCodeInAChallenge |
unit/verify | revert, verified |
| negative | TestRFC3579NASRefusesAResponseOffTheCurrentIdentifier |
unit/verify | revert, verified |
| negative | TestRadiusAdminEapRefusesAMalformedServerEAPHeader |
unit/verify | revert, verified |
| positive | TestRFC3579NASForwardsTheCurrentIdentifierBothWays |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapReadsTheServerEAPHeaderFields |
unit/verify | revert, verified |
RFC3579-2.2-2
If so, a new EAP-Response packet, if available, MUST be sent to the RADIUS server within an Access-Request, and the EAP-Message attribute(s) included within the Access-Challenge are silently discarded. (§2.2)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-2.2-2, so no unit is bound to it.
RFC3579-2.6.3-1
The NAS MUST make its access control decision based solely on the RADIUS Packet Type (Access-Accept/Access-Reject). (§2.6.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Access-Reject carrying EAP-Success denies (TestRadiusAdminEapDecisionFollowsTheRadiusCode) and Access-Accept carrying EAP-Failure at the identity round grants (TestRadiusAdminEapAcceptWithEapFailureStillAuthorizes); both directions, fixture chosen so an early return on eapErr would go red
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapAcceptWithEapFailureStillAuthorizes |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapDecisionFollowsTheRadiusCode |
unit/verify | revert, verified |
RFC3579-2.6.3-2
The access control decision MUST NOT be based on the contents of the EAP packet encapsulated in one or more EAP-Message attributes, if present. (§2.6.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. same pair as 2.6.3-1 read from the prohibition side: EAP content contradicting the code in either direction does not change the decision
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapDecisionFollowsTheRadiusCode |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAcceptWithEapFailureStillAuthorizes |
unit/verify | revert, verified |
RFC3579-2.6.3-3
Since the responsibility for avoiding conflicts lies with the RADIUS server, the NAS MUST NOT "manufacture" EAP packets in order to correct contradictory messages that it receives. (§2.6.3)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-2.6.3-3, so no unit is bound to it.
RFC3579-2.6.4-1
In order to ensure the correct processing of RADIUS packets, the NAS MUST first process the attributes, including the EAP-Message attribute(s), prior to processing the Accept/Reject indication. (§2.6.4)
Audit verdict: enforced (the tests do what the requirement demands), fresh. a concluding Access-Accept's EAP Notification (and, in the negative, an undecodable EAP-Message) reaches the log before the code decides; a loop that reads resp.Code first and returns would log nothing
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapProcessesAnUnparseableEAPMessageBeforeTheCode |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapProcessesTheEAPMessageBeforeTheCode |
unit/verify | revert, verified |
RFC3579-2.6.5-1
Reply-Message attribute(s) MUST NOT be included in any RADIUS message containing an EAP-Message attribute. (§2.6.5)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-2.6.5-1, so no unit is bound to it.
RFC3579-3-1
either NAS-Identifier, NAS-IP-Address or NAS-IPv6-Address attributes MUST be included. (§3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Row now quotes the MUST clause only (SHOULD half is RFC3579-3-2, {gap}). + TestRadiusAdminEapAccessRequestNamesTheNAS and TestRadiusAdminEapNamesTheNASWithoutASourceAddress: every Access-Request of the EAP conversation carries a non-empty NAS-Identifier, with and without a source address (one of the three suffices). - TestRadiusAdminEapWithNoNASIdentityIsNotSent: nasID empty and no IPv4 source -> Authenticate errors 'no NAS identity' and the server receives zero requests; observed red against the pre-fix exchange, which sent a zero-length NAS-Identifier. Producer exchange (authenticator.go) refuses before sending; NAS-IPv6-Address is never sent, so an IPv6-only source with no NAS-Identifier is refused, which is conservative, not non-conformant. Records at exchange observed red for all three units.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapWithNoNASIdentityIsNotSent |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAccessRequestNamesTheNAS |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapNamesTheNASWithoutASourceAddress |
unit/verify | revert, verified |
RFC3579-3.1-1
If multiple EAP-Message attributes are contained within an Access-Request or Access-Challenge packet, they MUST be in order and they MUST be consecutive attributes in the Access-Request or Access-Challenge packet. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. split at 253 in order (join reproduces the packet), no foreign attribute inside the run (Message-Authenticator and State after it), and receive-side concatenation around foreign attributes
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEAPMessageKeepsTheRunConsecutive |
unit/verify | revert, verified |
| positive | TestEAPMessageConcatenatesOnTheWayIn |
unit/verify | revert, verified |
| positive | TestEAPMessageSplitsAtTheAttributeLimit |
unit/verify | revert, verified |
RFC3579-3.1-2
Multiple EAP packets MUST NOT be encoded within EAP-Message attributes contained within a single Access-Challenge, Access-Accept, Access-Reject or Access-Request packet. (§3.1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. every sent Access-Request's EAP Length equals the whole run's octets, so a second packet riding along goes red; decoder refuses two separated runs in an Access-Challenge
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEAPMessageRefusesASecondRun |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapOneEAPPacketPerRadiusPacket |
unit/verify | revert, verified |
RFC3579-3.1-3
Therefore the Message-Authenticator attribute MUST be used to protect all Access-Request, Access-Challenge, Access-Accept, and Access-Reject packets containing an EAP-Message attribute. (§3.1, restated §3.2, §3.3 Note 1 and §4.3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. every EAP-bearing Access-Request carries a 16-octet Message-Authenticator that the mock server verifies; encodeRequest refuses an EAP-Message without the placeholder and replaces it with the HMAC. Ze sends only Access-Requests, so the Challenge/Accept/Reject clauses bind the server
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestEAPRequestWithoutMessageAuthenticatorIsRefused |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAccessRequestIsSignedAndCarriesEAPMessage |
unit/verify | revert, verified |
RFC3579-3.1-4
A NAS supporting the EAP-Message attribute MUST calculate the correct value of the Message-Authenticator and MUST silently discard the packet if it does not match the value sent. (§3.1, restated for any RADIUS client receiving an Access-Accept, Access-Reject or Access-Challenge at §3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. a forged challenge is discarded (retransmission observed, error is not a rejection); a verified challenge advances the conversation to a different second request
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapDiscardsUnauthenticatedChallenge |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapVerifiedChallengeIsAccepted |
unit/verify | revert, verified |
RFC3579-3.2-1
When present in an Access-Request packet, Message-Authenticator is an HMAC-MD5 [RFC2104] hash of the entire Access-Request packet, including Type, ID, Length and Authenticator, using the shared secret as the key, as follows. Message-Authenticator = HMAC-MD5 (Type, Identifier, Length, Request Authenticator, Attributes) When the message integrity check is calculated the signature string should be considered to be sixteen octets of zero. (§3.2)
Audit verdict: enforced (the tests do what the requirement demands), fresh. SignMessageAuthenticator matches an openssl HMAC-MD5 vector over the Access-Request, and a 0xff placeholder yields the same digest, so the field hashes as sixteen zero octets
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestSignMessageAuthenticatorZeroesTheSignatureField |
unit/verify | revert, verified |
| positive | TestSignMessageAuthenticatorMatchesRFC3579 |
unit/verify | revert, verified |
RFC3579-3.3-1
The EAP-Message and Message-Authenticator attributes specified in this document MUST NOT be present in an Accounting-Request. (§3.3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. encodeRequest refuses an Accounting-Request carrying EAP-Message or Message-Authenticator, and the control without either encodes
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAccountingRequestRefusesEAPAttributes |
unit/verify | revert, verified |
| positive | TestAccountingRequestRefusesEAPAttributes |
unit/verify | revert, verified |
RFC3579-3.3-2
An Access-Request that contains either a User-Password or CHAP-Password or ARAP-Password or one or more EAP-Message attributes MUST NOT contain more than one type of those four attributes. (§3.3 Note 1)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Rejudged 2026-10-14 by a reader who did not author the tests. (a) forbidden: an Access-Request carrying two of User-Password, CHAP-Password, ARAP-Password, EAP-Message. - TestAccessRequestRefusesTwoCredentialTypes drives all six pairs of the four types through encodeRequest and requires an error naming both types and zero octets; + TestRFC3579EachCredentialTypeAloneEncodes encodes each type alone, so the refusal is the pair's; - TestRFC3579ARAPBesideEAPIsRefusedAtExchange shows the guard at Client.Exchange, with no datagram reaching the server. Producer client.go oneCredentialType now names ARAP-Password (70), called by encodeRequest for every CodeAccessRequest. Several EAP-Message fragments (one type) are allowed by the code and not separately asserted.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestAccessRequestRefusesTwoCredentialTypes |
unit/verify | revert, verified |
| negative | TestRFC3579ARAPBesideEAPIsRefusedAtExchange |
unit/verify | revert, verified |
| positive | TestRFC3579EachCredentialTypeAloneEncodes |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAccessRequestIsSignedAndCarriesEAPMessage |
unit/verify | revert, verified |
RFC3579-4.2-1
Where RADIUS is run over IPsec ESP with a non-null transform, the secret shared between the NAS and the RADIUS server MAY NOT be configured. In this case, a shared secret of zero length MUST be assumed. (§4.2)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.2-1, so no unit is bound to it.
RFC3579-4.2-2
When IPsec ESP is used with RADIUS, per-packet authentication, integrity and replay protection MUST be used. 3DES-CBC MUST be supported as an encryption transform (§4.2)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.2-2, so no unit is bound to it.
RFC3579-4.2-3
HMAC-SHA1-96 MUST be supported as an authentication transform. (§4.2)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.2-3, so no unit is bound to it.
RFC3579-4.3.4-1
Where RADIUS shared secrets are configured, the RADIUS shared secret used by a NAS supporting EAP MUST NOT be reused by a NAS utilizing the User-Password attribute, since improper shared secret hygiene could lead to compromise of hidden attributes. (§4.3.4)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.3.4-1, so no unit is bound to it.
RFC3579-4.3.6-1
Should the NAS not be able to negotiate EAP, or should the EAP-Request sent by the NAS be of a different EAP type than what is expected, the authenticating peer MUST disconnect. (§4.3.6)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.3.6-1, so no unit is bound to it.
RFC3579-4.3.6-2
An authenticating peer expecting EAP to be negotiated for a session MUST NOT negotiate a weaker method, such as CHAP or PAP. (§4.3.6)
Audit verdict: enforced (the tests do what the requirement demands), fresh. a successful and a rejected eap-mschapv2 login put an EAP-Message and no User-Password or CHAP-Password on every request, and the rejection produces no weaker retry
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapDoesNotDowngradeAfterARejection |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapNeverSendsAPasswordCredential |
unit/verify | revert, verified |
RFC3579-4.3.6-3
In such cases, if any peers of the NAS MUST do EAP, then the NAS MUST attempt to negotiate EAP for every session. (§4.3.6)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.3.6-3, so no unit is bound to it.
RFC3579-4.3.6-4
The authenticating peer MUST refuse to renegotiate authentication, even if the renegotiation is from CHAP to EAP. (§4.3.6, restated in the same section for an EAP-capable peer)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.3.6-4, so no unit is bound to it.
RFC3579-4.3.6-5
If EAP is negotiated but is not supported by the RADIUS proxy or server, then the server or proxy MUST respond with an Access-Reject. In these cases, a PPP NAS MUST send an LCP-Terminate and disconnect the peer. (§4.3.6)
Audit verdict: not audited: no reader has judged these tests
No test carries RFC3579-4.3.6-5, so no unit is bound to it.
RFC3579-3-2
The NAS-Port or NAS-Port-Id attributes SHOULD be included by the NAS in Access-Request packets (§3)
Audit verdict: enforced (the tests do what the requirement demands), fresh. Re-judged 2026-10-18 (independent auditor, after d12a30ef66). RFC 3579 Section 3: "The NAS-Port or NAS-Port-Id attributes SHOULD be included by the NAS in Access-Request packets"; every EAP-bearing Access-Request ze sends is an admin login's, built by (*radiusAuthenticator).exchange, which now appends NAS-Port-Id from AuthRequest.Service, and the only RADIUS-reaching logins name a channel (ssh/passwordauth.go "ssh", web/auth.go "web"; the API authenticates locally). The L2TP subscriber Access-Request is outside this RFC's scope because it never carries EAP-Message, and it sends NAS-Port anyway. The recorded discrimination breaks (exchange body replaced by panic) only fail the whole login, so they prove nothing about the attribute; auditor overlay mutants did: dropping the NAS-Port-Id append, or passing "" from Authenticate or authenticateEAP, turns the ssh/web EAP subtests and the PAP test red, and a constant "ssh" port turns the web and no-channel subtests red. The tagged negative (no channel, no attribute) checks RFC 2865 Section 5 more than this SHOULD, and its zero-length clause is discharged by EncodeTo, which drops empty attributes (an unconditional-append mutant survives as wire-equivalent); its real value is catching a fixed port. aaa-radius-admin.ci shows the mock server reading nas-port-id=ssh end to end, and web/auth_test.go TestWebLoginsNameTheWebChannel covers the web hand-off untagged.
| Polarity | Test | Kind and tier | Proof state |
|---|---|---|---|
| negative | TestRadiusAdminEapAccessRequestNamesThePort |
unit/verify | revert, verified |
| positive | TestRadiusAdminEapAccessRequestNamesThePort |
unit/verify | revert, verified |
| positive | TestRadiusAdminPapAccessRequestNamesThePort |
unit/verify | revert, verified |
| positive | aaa-radius-admin.ci |
functional/verify | revert, verified |
Extraction sign-off
| Field | Value |
|---|---|
| Reviewer | claude |
| Signed off | 2026-09-27 |
| Register | rfc2119 |
| Source | rfc/full/rfc3579.txt |
| Source fingerprint | af4e5a944b99ad93 |
| Record | rfc/extraction/rfc3579.json |
| Mapped sentences | 30 |
| Declined as scope | 26 |
| Relocated to a spec, which Ze OWES | 0 |
| Unclassified | 0 |
Sections
| Section | Name | Sites | Disposition | Reason |
|---|---|---|---|---|
front |
not stated | 0 | skipped (front-matter) | Title block, Status of this Memo, copyright notice, Abstract and table of contents. The Abstract says what the memo adds to RADIUS and binds no speaker. |
1 |
Introduction | 3 | walked | Introduction. States what RADIUS and EAP are, and carries the RFC 2865 rule that a NAS must not implement the attributes for a service it cannot offer, in its EAP form. |
1.1 |
Specification of Requirements | 0 | walked | Specification of Requirements. The RFC 2119 key-words paragraph. No obligation of its own. |
1.2 |
Terminology | 2 | walked | Terminology. Defines authenticator, peer, authentication server, silently discard, displayable message, NAS, service and session. Two of those definitions carry obligations, sites 1.2:1 and 1.2:2; 'silently discard' carries two SHOULDs captured as RFC3579-1.2-3. |
2 |
RADIUS Support for EAP | 0 | walked | RADIUS Support for EAP. Says why the pass-through architecture exists and that a NAS may mix local authentication with pass-through, which is the MAY captured as RFC3579-2-1. |
2.1 |
Protocol Overview | 8 | walked | Protocol Overview. The conversation itself: who sends the first EAP-Request, how the NAS encapsulates a Response, what ends the conversation, EAP-Start, and the User-Name copying rule that lets a non-EAP-aware proxy forward the request. |
2.2 |
Invalid Packets | 3 | walked | Invalid Packets. The NAS header validation, the Error-Cause 202 branch, and the RADIUS server's fatal and non-fatal error handling. The DoS advice at the end is written as 'it is advisable' and 'is recommended' in lower case, and binds nobody. |
2.3 |
Retransmission | 0 | walked | Retransmission. Describes how Session-Timeout in an Access-Challenge sets the EAP retransmission timer for that one EAP-Request. Indicative prose, no obligation. |
2.4 |
Fragmentation | 1 | walked | Fragmentation. One obligation, on the RADIUS server, not to exceed a Framed-MTU the NAS supplied. The NAS half is written as 'may be included'. |
2.5 |
Alternative Uses | 1 | walked | Alternative Uses. RADIUS-encapsulated EAP between a RADIUS server and a security server. One obligation, on the RADIUS server. |
2.6 |
Usage Guidelines | 0 | walked | Usage Guidelines. A heading over 2.6.1 to 2.6.5 with no body text of its own. |
2.6.1 |
Identifier Space | 1 | walked | Identifier Space. One obligation, on RADIUS server implementations, to keep the EAP Identifier spaces of distinct sessions apart. |
2.6.2 |
Role Reversal | 1 | walked | Role Reversal. Says role reversal is not supported, with the obligation on the RADIUS server to reject an Access-Request encapsulating an EAP-Request, and a SHOULD on the same actor about the Nak it includes. |
2.6.3 |
Conflicting Messages | 3 | walked | Conflicting Messages. Three NAS obligations, all captured, plus the SHOULD list of combinations a RADIUS server is told not to send. |
2.6.4 |
Priority | 1 | walked | Priority. One NAS obligation about the order in which attributes and the Accept/Reject indication are processed. |
2.6.5 |
Displayable Messages | 2 | walked | Displayable Messages. The RADIUS server's encapsulation obligation, the exclusion of Reply-Message from any EAP-bearing message, and the NAS SHOULD to discard a Reply-Message rather than translate it. |
3 |
Attributes | 2 | walked | Attributes. The NAS identification attributes an Access-Request carries, and the RADIUS server's obligation to echo User-Name. |
3.1 |
EAP-Message | 6 | walked | EAP-Message. The attribute format, the ordering and single-EAP-packet rules, the Message-Authenticator protection rule, and the calculate-and-discard obligations on each of the two roles. |
3.2 |
Message-Authenticator | 3 | walked | Message-Authenticator. The attribute format and the HMAC-MD5 construction. The construction itself is written without an RFC 2119 keyword, so the site scan does not see it, and it is declared here as an unsourced id: 'MUST calculate the correct value' at sites 3.1:4 and 3.1:6 has no meaning without the formula this section states. The response-side paragraph, 'For Access-Challenge, Access-Accept, and Access-Reject packets, the Message-Authenticator is calculated as follows' through 'The Message-Authenticator is calculated and inserted in the packet before the Response Authenticator is calculated.', binds whoever writes those three packets, the RADIUS server: ze writes none of them (the admin and L2TP paths only send Access-Requests, and the CoA listener's reply, (*coaListener).sendResponse in internal/component/l2tp/plugins/authradius/coa.go, carries no Message-Authenticator). The client's side of that formula, recomputing it over a received reply with the Request Authenticator in place, is RFC3579-3.1-4. The narrowing audit of 2026-09-28 called the ordering sentence dropped from RFC3579-3.2-1; it is recorded here and not added to that row, because no Ze producer performs it. |
3.3 |
Table of Attributes | 4 | walked | Table of Attributes. One obligation in the body, that neither attribute appears in an Accounting-Request. The table rows, its three notes and its legend follow in this section: Note 1 carries two obligations and the legend carries none. |
4 |
Security Considerations | 0 | walked | Security Considerations. A heading over 4.1 to 4.3 with no body text of its own. |
4.1 |
Security Requirements | 0 | walked | Security Requirements. The ten-item threat list and the statement that confidentiality, data origin authentication, integrity and replay protection are needed. Written in indicative prose with no keyword. |
4.2 |
Security Protocol | 4 | walked | Security Protocol. The IPsec profile for RADIUS: the transforms that must be supported, the zero-length shared secret where ESP with a non-null transform carries the traffic, and the IKE mode and identity payload advice. |
4.3 |
Security Issues | 0 | walked | Security Issues. A heading and the list of the ten vulnerabilities 4.3.1 to 4.3.10 expand. |
4.3.1 |
Privacy Issues | 0 | walked | Privacy Issues. One SHOULD, to protect RADIUS with IPsec ESP, restating Section 4.2's advice. |
4.3.2 |
Spoofing and Hijacking | 1 | walked | Spoofing and Hijacking. The SHOULD to use Message-Authenticator in an Access-Request with no User-Password, captured as RFC3579-4.3.2-1, and the restatement of the Section 3.1 protection rule. |
4.3.3 |
Dictionary Attacks | 0 | walked | Dictionary Attacks. Quotes RFC 2865's shared-secret advice and recommends IPsec ESP. The quoted SHOULD belongs to RFC 2865. |
4.3.4 |
Known Plaintext Attacks | 1 | walked | Known Plaintext Attacks. Explains the User-Password keystream reuse problem and states one obligation, that an EAP NAS's shared secret is not reused by a NAS using User-Password. |
4.3.5 |
Replay Attacks | 0 | walked | Replay Attacks. Describes what RADIUS does and does not give for replay protection. Indicative prose, no obligation. |
4.3.6 |
Negotiation Attacks | 8 | walked | Negotiation Attacks. The downgrade rules: what the authenticating peer must do when EAP was expected, what the NAS must attempt, and what the RADIUS server or proxy must answer. |
4.3.7 |
Impersonation | 1 | walked | Impersonation. Quotes RFC 2865 Section 3 on choosing the shared secret by source address, and states SHOULDs on RADIUS proxies. Ze is neither the RADIUS server nor a proxy. |
4.3.8 |
Man in the Middle Attacks | 0 | walked | Man in the Middle Attacks. One SHOULD, that EAP methods incorporate their own per-packet integrity protection. That obligation is on the EAP method, which RFC 3748 and the method's own RFC govern. |
4.3.9 |
Separation of Authenticator and Authentication Server | 0 | walked | Separation of Authenticator and Authentication Server. Explains what mutual authentication means when the two are on different hosts, and that the MSK must reach the authenticator. The key transport mechanism is stated to be out of scope for this document. |
4.3.10 |
Multiple Databases | 0 | walked | Multiple Databases. Recommends consolidating the security server's and the RADIUS server's user stores. No obligation, and the actor is the deployment. |
5 |
IANA Considerations | 0 | skipped (iana) | IANA Considerations. 'This specification does not create any new registries, or define any new RADIUS attributes or values.' |
6 |
References | 0 | skipped (references) | References. A heading over 6.1 and 6.2. |
6.1 |
not stated | 0 | skipped (references) | Normative References: RFC 1321, 2104, 2119, 2279, 2284, 2401, 2406, 2409, 2486, 2865, 2988, 3162, 3280 and 3576. |
6.2 |
not stated | 0 | skipped (references) | Informative References, and the non-RFC citations IEEE802, IEEE8021X, MD5Attack, Masters and NASREQ. |
Excluded sentences
| Site | Excluded kind | Reason | Quote |
|---|---|---|---|
1:1 |
cross-documentnever bound Ze the obligation belongs to another document that this one only cites |
The sentence opens 'As noted in [RFC2865]' and restates RFC 2865 Section 1.1. The obligation belongs to RFC 2865, whose summary carries it as RFC2865-1.1-1. | As noted in [RFC2865], a Network Access Server (NAS) that does not implement a given service MUST NOT implement the RADIUS attributes for that service. |
2.1:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The sentence names 'a RADIUS server compliant with this specification and wishing to authenticate with EAP' as the actor. | On receiving a valid Access-Request packet containing EAP-Message attribute(s), a RADIUS server compliant with this specification and wishing to authenticate with EAP MUST respond with an Access-Challenge packet containing EAP-Message attribute(s). |
2.1:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is the RADIUS server that does not support EAP. | If the RADIUS server does not support EAP or does not wish to authenticate with EAP, it MUST respond with an Access-Reject. |
2.1:6 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'the local RADIUS server' deciding a realm from the peer identity. | If the realm is determined based on the peer identity, the local RADIUS server MUST respond with a RADIUS Access-Challenge including an EAP-Message attribute encapsulating an EAP-Request/Identity packet. |
2.1:7 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The Access-Reject is sent by the RADIUS server that does not support the EAP-Message attribute. The NAS half of the same paragraph, denying access on that reject, is site 2.1:8. | If an Access-Request is sent to a RADIUS server which does not support the EAP-Message attribute, then an Access-Reject MUST be sent in response. |
2.1:8 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Restates site 2.1:3, 'Reception of a RADIUS Access-Reject packet MUST result in the NAS denying access to the authenticating peer', for the particular reject an EAP-incapable server sends. It adds no obligation RFC3579-2.1-1 does not already carry. | On receiving an Access-Reject, the NAS MUST deny access to the authenticating peer. |
2.2:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'A RADIUS server determining that a fatal error has occurred'. | A RADIUS server determining that a fatal error has occurred MUST send an Access-Reject containing an EAP-Message attribute encapsulating EAP-Failure. |
2.4:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'A RADIUS server having received a Framed-MTU attribute'. The NAS half of Section 2.4, supplying Framed-MTU, is written as 'may be included' and states no obligation. | A RADIUS server having received a Framed-MTU attribute in an Access-Request packet MUST NOT send any subsequent packet in this EAP conversation containing EAP-Message attributes whose values, when concatenated, exceed the length specified by the Framed-MTU value, taking the link type (specified by the NAS-Port-Type attribute) into account. |
2.5:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. Section 2.5 describes a RADIUS server talking to a security server, and the actor is the RADIUS server adding the missing Access-Accept attributes. | This means that the RADIUS server MUST add these attributes prior to sending an Access-Accept message to the NAS. |
2.6.1:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'RADIUS server implementations' keeping EAP Identifier spaces apart per session. | RADIUS server implementations MUST be able to distinguish between EAP packets with the same Identifier existing within distinct sessions, originating on the same NAS. |
2.6.2:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is the RADIUS server refusing a role-reversed Access-Request that encapsulates an EAP-Request. | A RADIUS server MUST respond to an Access-Request encapsulating an EAP-Request with an Access-Reject. |
2.6.5:1 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is the RADIUS server sending a displayable message to a NAS. | When sending a displayable message to a NAS during an EAP conversation, the RADIUS server MUST encapsulate displayable messages within EAP-Message/EAP-Request/Notification attribute(s). |
3:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is the RADIUS server echoing User-Name into its Access-Accept. | In order to permit forwarding of the Access-Reply by EAP-unaware proxies, if a User-Name attribute was included in an Access-Request, the RADIUS server MUST include the User-Name attribute in subsequent Access-Accept packets. |
3.1:4 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'A RADIUS server supporting the EAP-Message attribute'. The NAS form of the same check is site 3.1:6. | A RADIUS server supporting the EAP-Message attribute MUST calculate the correct value of the Message-Authenticator and MUST silently discard the packet if it does not match the value sent. |
3.1:5 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'A RADIUS server not supporting the EAP-Message attribute'. | A RADIUS server not supporting the EAP-Message attribute MUST return an Access-Reject if it receives an Access-Request containing an EAP-Message attribute. |
3.2:1 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Restates site 3.1:3 from the Message-Authenticator side: the attribute is mandatory in any of the four packet types that includes an EAP-Message. It adds no obligation RFC3579-3.1-3 does not already carry. | It MUST be used in any Access-Request, Access-Accept, Access-Reject or Access-Challenge that includes an EAP-Message attribute. |
3.2:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'A RADIUS server receiving an Access-Request with a Message-Authenticator attribute present'. | A RADIUS server receiving an Access-Request with a Message-Authenticator attribute present MUST calculate the correct value of the Message-Authenticator and silently discard the packet if it does not match the value sent. |
3.2:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Restates site 3.1:6 for a RADIUS client rather than for a NAS supporting EAP-Message: recompute the Message-Authenticator of a received Access-Accept, Access-Reject or Access-Challenge and silently discard on a mismatch. One behaviour, one code path in ze (verifyResponseMessageAuthenticator), so it maps to the same requirement. | A RADIUS client receiving an Access-Accept, Access-Reject or Access-Challenge with a Message-Authenticator attribute present MUST calculate the correct value of the Message-Authenticator and silently discard the packet if it does not match the value sent. |
3.3:3 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Note 1 restates site 3.1:3, 'If any packet type contains an EAP-Message attribute it MUST also contain a Message-Authenticator'. It adds no obligation RFC3579-3.1-3 does not already carry. | If any packet type contains an EAP-Message attribute it MUST also contain a Message-Authenticator. |
3.3:4 |
not-a-requirementnever bound Ze the sentence states a fact or describes another document, and directs no implementation |
The legend of the Section 3.3 table, defining what the cells 0, 0+, 0-1, 1 and 1+ mean. The keywords describe the notation, not a speaker's behaviour; the obligations the table expresses are carried by Note 1 and by the attribute sections. | 0 This attribute MUST NOT be present. 0+ Zero or more instances of this attribute MAY be present. 0-1 Zero or one instance of this attribute MAY be present. 1 Exactly one instance of this attribute MUST be present. 1+ One or more of these attributes MUST be present. |
4.2:2 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'a RADIUS server that cannot know whether incoming traffic is IPsec-protected'. The client-side half of the same paragraph is site 4.2:1. | However, a RADIUS server that cannot know whether incoming traffic is IPsec-protected MUST be configured with a non-null RADIUS shared secret. |
4.3.2:1 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
The Security Issues restatement of site 3.1:3, 'the Message-Authenticator attribute MUST be used in all RADIUS packets containing an EAP-Message attribute'. It adds no obligation RFC3579-3.1-3 does not already carry. | To provide stronger security, the Message-Authenticator attribute MUST be used in all RADIUS packets containing an EAP-Message attribute. |
4.3.6:4 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is the RADIUS server answering a CHAP Access-Request where EAP is required. | However, if CHAP has been negotiated but EAP is required, the RADIUS server MUST respond with an Access-Reject, rather than an Access-Challenge/EAP-Message/EAP-Request packet. |
4.3.6:6 |
binds-another-rolenever bound Ze the obligation is addressed to a role Ze never acts as Presumed wrong until justified: Ze rarely implements one side of a protocol, so the reason beside this row must name the role, show Ze never acts as it, and cite the producer that would. |
Binds the RADIUS authentication server. Ze never acts as one: NewClient (internal/component/radius/client.go) binds an ephemeral UDP socket with no service port, and (*Client).readLoop dispatches a datagram only against a waiter that (*Client).Exchange registered for one of ze's own outstanding requests, so no Access-Request receive path exists in the tree. If ze ran a RADIUS server the listener would live beside that producer. The actor is 'the server or proxy' that does not support EAP. Ze is neither a RADIUS server nor a RADIUS proxy: it forwards no other party's RADIUS packet. | If EAP is negotiated but is not supported by the RADIUS proxy or server, then the server or proxy MUST respond with an Access-Reject. |
4.3.6:8 |
duplicate-ofnever bound Ze the same obligation is already captured under another requirement id |
Restates site 4.3.6:5 one paragraph later, for an EAP-capable peer rather than for the peer generally. It adds no obligation RFC3579-4.3.6-4 does not already carry. | An EAP-capable authenticating peer MUST refuse to renegotiate the authentication protocol if EAP had initially been negotiated. |
4.3.7:1 |
cross-documentnever bound Ze the obligation belongs to another document that this one only cites |
The sentence is the body of a block quotation introduced by '[RFC2865] Section 3 states:'. The obligation belongs to RFC 2865, whose summary is rfc/short/rfc2865.md, and it binds the RADIUS server in any case. | A RADIUS server MUST use the source IP address of the RADIUS UDP packet to decide which shared secret to use, so that RADIUS requests can be proxied. |
Superseded
No document obsoletes RFC 3579, so its obligations are stated where they were written.