From f1101e0c0171155ae72d013ca80570092a75d00b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sat, 24 May 2025 02:13:35 +0200 Subject: [PATCH] mostly parsing eavp extensions Signed-off-by: Jens Langhammer --- .../radius/eap/protocol/eap/payload.go | 12 +++++++----- .../radius/eap/protocol/peap/extension.go | 18 ++++++++++++++++-- .../radius/eap/protocol/peap/extension_avp.go | 19 +++++++++++++++++++ .../radius/eap/protocol/peap/payload.go | 6 ++++++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/internal/outpost/radius/eap/protocol/eap/payload.go b/internal/outpost/radius/eap/protocol/eap/payload.go index 702c73334d..80900498a8 100644 --- a/internal/outpost/radius/eap/protocol/eap/payload.go +++ b/internal/outpost/radius/eap/protocol/eap/payload.go @@ -46,12 +46,14 @@ func (p *Payload) Decode(raw []byte) error { } log.WithField("raw", debug.FormatBytes(raw)).Trace("EAP: decode raw") p.RawPayload = raw[5:] - pp, _, err := EmptyPayload(p.Settings, p.MsgType) - if err != nil { - return err + if p.Payload == nil { + pp, _, err := EmptyPayload(p.Settings, p.MsgType) + if err != nil { + return err + } + p.Payload = pp } - p.Payload = pp - err = p.Payload.Decode(raw[5:]) + err := p.Payload.Decode(raw[5:]) if err != nil { return err } diff --git a/internal/outpost/radius/eap/protocol/peap/extension.go b/internal/outpost/radius/eap/protocol/peap/extension.go index d64c04ede6..216e6337fa 100644 --- a/internal/outpost/radius/eap/protocol/peap/extension.go +++ b/internal/outpost/radius/eap/protocol/peap/extension.go @@ -1,7 +1,7 @@ package peap import ( - "errors" + "encoding/binary" log "github.com/sirupsen/logrus" "goauthentik.io/internal/outpost/radius/eap/protocol" @@ -14,7 +14,21 @@ type ExtensionPayload struct { } func (ep *ExtensionPayload) Decode(raw []byte) error { - return errors.New("PEAP: Extension Payload does not support decoding") + ep.AVPs = []ExtensionAVP{} + offset := 0 + for { + if len(raw[offset:]) < 4 { + return nil + } + len := binary.BigEndian.Uint16(raw[offset+2:offset+2+2]) + ExtensionHeaderSize + avp := &ExtensionAVP{} + err := avp.Decode(raw[offset : offset+int(len)]) + if err != nil { + return err + } + ep.AVPs = append(ep.AVPs, *avp) + offset = offset + int(len) + } } func (ep *ExtensionPayload) Encode() ([]byte, error) { diff --git a/internal/outpost/radius/eap/protocol/peap/extension_avp.go b/internal/outpost/radius/eap/protocol/peap/extension_avp.go index 324d472ee3..4b6f53a77b 100644 --- a/internal/outpost/radius/eap/protocol/peap/extension_avp.go +++ b/internal/outpost/radius/eap/protocol/peap/extension_avp.go @@ -2,6 +2,7 @@ package peap import ( "encoding/binary" + "fmt" ) type AVPType uint16 @@ -10,6 +11,8 @@ const ( AVPAckResult AVPType = 3 ) +const ExtensionHeaderSize = 4 + type ExtensionAVP struct { Mandatory bool Type AVPType // 14-bit field @@ -17,6 +20,22 @@ type ExtensionAVP struct { Value []byte } +func (eavp *ExtensionAVP) Decode(raw []byte) error { + typ := binary.BigEndian.Uint16(raw[:2]) + // TODO fix this + if typ&0b1000000000000000 == 0 { + eavp.Mandatory = true + } + // TODO: Check reserved bit + eavp.Type = AVPType(typ & 0b0011111111111111) + eavp.Length = binary.BigEndian.Uint16(raw[2:4]) + val := raw[4:] + if eavp.Length != uint16(len(val)) { + return fmt.Errorf("PEAP-Extension: Invalid length: %d, should be %d", eavp.Length, len(val)) + } + return nil +} + func (eavp ExtensionAVP) Encode() []byte { buff := []byte{ 0, diff --git a/internal/outpost/radius/eap/protocol/peap/payload.go b/internal/outpost/radius/eap/protocol/peap/payload.go index 0907b05583..6be31f1016 100644 --- a/internal/outpost/radius/eap/protocol/peap/payload.go +++ b/internal/outpost/radius/eap/protocol/peap/payload.go @@ -80,6 +80,12 @@ func (p *Payload) eapInnerDecode(ctx protocol.Context) (*eap.Payload, error) { fullLength := len(p.raw) + len(fixedRaw) binary.BigEndian.PutUint16(fixedRaw[2:], uint16(fullLength)) fixedRaw = append(fixedRaw, p.raw...) + // If the raw data has a msgtype set to type 33 (EAP extension), decode differently + if len(p.raw) > 5 && p.raw[4] == byte(TypePEAPExtension) { + ep.Payload = &ExtensionPayload{} + // Pass original raw data to EAP as extension payloads are encoded like normal EAP packets + fixedRaw = p.raw + } err := ep.Decode(fixedRaw) if err != nil { return nil, err