eap

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2026 License: MIT Imports: 15 Imported by: 0

README

Go Report Card pkg.go.dev

radius-eap

A production-oriented implementation of common EAP methods for RADIUS in Go — race-free, state-safe, and tested clause-by-clause against the relevant RFCs.

Supported methods

EAP method Type Specification
Identity 1 RFC 3748 Section 5.1
Legacy Nak 3 RFC 3748 Section 5.3.1
GTC (OTP, in-tunnel) 6 RFC 3748 Section 5.6
EAP-TLS 13 RFC 5216 / RFC 9190
PEAP (PEAPv0) 25 draft-josefsson / draft-kamath
MS-CHAP-v2 26 RFC 2759 / RFC 3079

Documentation

Architecture and per-protocol RFC references live in _RFC.md, which indexes a detailed document (with diagrams) for each protocol. Start there to see how a protocol works and which file/function implements which RFC clause.

Usage

Implement protocol.StateManager (or use the bundled eap.NewMemoryStateManager, a concurrency-safe store with TTL eviction), then decode the EAP-Message from each RADIUS request and let the library drive the exchange:

sm := eap.NewMemoryStateManager(settings, 5*time.Minute)
defer sm.Close()

func (s *Server) ServeRADIUS(w radius.ResponseWriter, r *radius.Request) {
    raw := rfc2869.EAPMessage_Get(r.Packet)
    if len(raw) == 0 {
        return
    }
    pkt, err := eap.Decode(sm, raw)
    if err != nil {
        return
    }
    pkt.HandleRadiusPacket(w, r) // writes Access-Challenge/Accept/Reject
}

See examples/server for a complete EAP-TLS + PEAP-MSCHAPv2 server.

Testing

make test       # unit tests + eapol_test integration
make test-race  # the full suite under the race detector

Integration tests use eapol_test (sudo apt install eapoltest) and a minimal PKI (a CA, a server certificate, and — for EAP-TLS — a client certificate). Run a client against the server with:

eapol_test -c peap.conf -s foo -a <radius-server-ip>
PEAP (phase 2: MS-CHAP-v2)
network={
    ssid="DoesNotMatterForThisTest"
    key_mgmt=WPA-EAP
    eap=PEAP
    identity="foo"
    password="bar"
    ca_cert="ca.pem"
    phase2="auth=MSCHAPV2"
}
EAP-TLS
network={
    ssid="DoesNotMatterForThisTest"
    key_mgmt=WPA-EAP
    eap=TLS
    identity="foo"
    ca_cert="ca.pem"
    client_cert="cert_client.pem"
    private_key="cert_client.key"
    eapol_flags=3
    eap_workaround=0
}

Acknowledgements

Originally forked from BeryJu/radius-eap; see BeryJu's write-up Implementing EAP. This fork has since been substantially reworked (race-free EAP-TLS transport, session-safe state handling, DoS hardening, RFC documentation, and expanded tests).

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultLogger

func DefaultLogger() *stdLogger

Types

type MemoryStateManager added in v0.2.0

type MemoryStateManager struct {
	// contains filtered or unexported fields
}

MemoryStateManager is a ready-to-use, concurrency-safe protocol.StateManager backed by an in-memory map with time-based eviction. It exists so consumers do not have to re-implement the same map+mutex+TTL boilerplate (and so they avoid the unbounded-growth bug of a naive map that never evicts abandoned EAP sessions).

A single MemoryStateManager serves one EAP configuration (protocol.Settings). Construct it once at startup and share it across requests.

func NewMemoryStateManager added in v0.2.0

func NewMemoryStateManager(settings protocol.Settings, ttl time.Duration) *MemoryStateManager

NewMemoryStateManager returns a MemoryStateManager for the given settings. If ttl > 0 a background goroutine evicts sessions whose last access is older than ttl; ttl <= 0 disables eviction (sessions live until the process exits). Call Close to stop the eviction goroutine when the manager is no longer needed.

func (*MemoryStateManager) Close added in v0.2.0

func (m *MemoryStateManager) Close()

Close stops the background eviction goroutine. It is safe to call more than once.

func (*MemoryStateManager) Delete added in v0.2.0

func (m *MemoryStateManager) Delete(key string)

Delete removes a session immediately, e.g. once authentication has resolved.

func (*MemoryStateManager) GetEAPSettings added in v0.2.0

func (m *MemoryStateManager) GetEAPSettings() protocol.Settings

func (*MemoryStateManager) GetEAPState added in v0.2.0

func (m *MemoryStateManager) GetEAPState(key string) *protocol.State

func (*MemoryStateManager) Len added in v0.2.0

func (m *MemoryStateManager) Len() int

Len reports the number of live sessions. Primarily useful for tests/metrics.

func (*MemoryStateManager) SetEAPState added in v0.2.0

func (m *MemoryStateManager) SetEAPState(key string, state *protocol.State)

type Packet

type Packet struct {
	// contains filtered or unexported fields
}

func Decode

func Decode(stm protocol.StateManager, raw []byte) (*Packet, error)

Decode parses the raw EAP-Message bytes from a RADIUS Access-Request into a Packet ready for HandleRadiusPacket. The StateManager supplies the method settings used to resolve the inner method payload. It returns an error if the bytes are not a well-formed EAP packet.

func (*Packet) Encode

func (p *Packet) Encode() ([]byte, error)

Encode serializes the packet's EAP payload into the bytes to place in the outbound EAP-Message attribute.

func (*Packet) HandleRadiusPacket

func (p *Packet) HandleRadiusPacket(w radius.ResponseWriter, r *radius.Request)

HandleRadiusPacket processes one decoded EAP Access-Request and writes the RADIUS response. It resolves the session State, runs the EAP method state machine (handleEAP), maps the resulting EAP Code to a RADIUS code (Request→Access-Challenge, Success→Access-Accept, Failure→Access-Reject), applies any registered response modifiers, attaches the State on challenges, and finally sets the RFC 2869 Message-Authenticator. It never returns an error: failures are turned into an Access-Reject.

Directories

Path Synopsis
examples
server command
eap
gtc
tls

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL