separate eap logic into protocol

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer
2025-05-21 00:53:18 +02:00
parent 19bb77638a
commit 1575b96262
10 changed files with 185 additions and 89 deletions

View File

@ -18,6 +18,8 @@ type Context interface {
Packet() *radius.Request
ProtocolSettings() interface{}
StateForProtocol(p Type) interface{}
GetProtocolState() interface{}
SetProtocolState(interface{})

View File

@ -0,0 +1,83 @@
package eap
import (
"encoding/binary"
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"goauthentik.io/internal/outpost/radius/eap/debug"
"goauthentik.io/internal/outpost/radius/eap/protocol"
)
const TypeEAP protocol.Type = 0
func Protocol() protocol.Payload {
return &Payload{}
}
type Payload struct {
Code protocol.Code
ID uint8
Length uint16
MsgType protocol.Type
Payload protocol.Payload
RawPayload []byte
}
func (ip *Payload) Type() protocol.Type {
return TypeEAP
}
func (ip *Payload) Offerable() bool {
return false
}
func (packet *Payload) Decode(raw []byte) error {
packet.Code = protocol.Code(raw[0])
packet.ID = raw[1]
packet.Length = binary.BigEndian.Uint16(raw[2:])
if packet.Length != uint16(len(raw)) {
return errors.New("mismatched packet length")
}
if len(raw) > 4 && (packet.Code == protocol.CodeRequest || packet.Code == protocol.CodeResponse) {
packet.MsgType = protocol.Type(raw[4])
}
packet.RawPayload = raw[5:]
if packet.Payload == nil {
return nil
}
log.WithField("raw", debug.FormatBytes(raw)).WithField("payload", fmt.Sprintf("%T", packet.Payload)).Debug("EAP: decode raw")
err := packet.Payload.Decode(raw[5:])
if err != nil {
return err
}
return nil
}
func (p *Payload) Encode() ([]byte, error) {
buff := make([]byte, 4)
buff[0] = uint8(p.Code)
buff[1] = uint8(p.ID)
if p.Payload != nil {
payloadBuffer, err := p.Payload.Encode()
if err != nil {
return buff, err
}
if p.Code == protocol.CodeRequest || p.Code == protocol.CodeResponse {
buff = append(buff, uint8(p.MsgType))
}
buff = append(buff, payloadBuffer...)
}
binary.BigEndian.PutUint16(buff[2:], uint16(len(buff)))
return buff, nil
}
func (ip *Payload) Handle(ctx protocol.Context) protocol.Payload {
ctx.Log().Debug("EAP: Handle")
ctx.SetProtocolState(&State{
PacketID: ip.ID,
})
return nil
}

View File

@ -0,0 +1,5 @@
package eap
type State struct {
PacketID uint8
}

View File

@ -9,3 +9,12 @@ type Payload interface {
}
type Type uint8
type Code uint8
const (
CodeRequest Code = 1
CodeResponse Code = 2
CodeSuccess Code = 3
CodeFailure Code = 4
)

View File

@ -4,6 +4,8 @@ import (
log "github.com/sirupsen/logrus"
"goauthentik.io/internal/outpost/radius/eap/debug"
"goauthentik.io/internal/outpost/radius/eap/protocol"
"goauthentik.io/internal/outpost/radius/eap/protocol/eap"
"goauthentik.io/internal/outpost/radius/eap/protocol/identity"
"goauthentik.io/internal/outpost/radius/eap/protocol/tls"
)
@ -11,11 +13,14 @@ const TypePEAP protocol.Type = 25
func Protocol() protocol.Payload {
return &tls.Payload{
Inner: &Payload{},
Inner: &Payload{
Inner: &eap.Payload{},
},
}
}
type Payload struct {
Inner protocol.Payload
}
func (p *Payload) Type() protocol.Type {
@ -33,7 +38,16 @@ func (p *Payload) Encode() ([]byte, error) {
}
func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
log.Debug("PEAP: Handle")
eapState := ctx.StateForProtocol(eap.TypeEAP).(*eap.State)
if !ctx.IsProtocolStart() {
ctx.Log().Debug("PEAP: Protocol start")
return &eap.Payload{
Code: protocol.CodeRequest,
ID: eapState.PacketID,
MsgType: identity.TypeIdentity,
Payload: &identity.Payload{},
}
}
return &Payload{}
}

View File

@ -4,18 +4,19 @@ import (
"goauthentik.io/internal/outpost/radius/eap/protocol"
)
func (p *Payload) innerHandler(ctx protocol.Context) *Payload {
func (p *Payload) innerHandler(ctx protocol.Context) {
// p.st.TLS.read
// d, _ := io.ReadAll(p.st.TLS)
err := p.Inner.Decode([]byte{})
if err != nil {
ctx.Log().WithError(err).Warning("TLS: failed to decode inner protocol")
ctx.EndInnerProtocol(protocol.StatusError, nil)
return nil
return
}
pl := p.Inner.Handle(ctx)
enc, err := pl.Encode()
return &Payload{
Data: enc,
}
p.st.TLS.Write(enc)
// return &Payload{
// Data: enc,
// }
}

View File

@ -124,7 +124,8 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
defer p.st.ContextCancel()
if p.Inner != nil {
ctx.Log().Debug("TLS: Handshake is done, delegating to inner protocol")
return p.innerHandler(ctx)
p.innerHandler(ctx)
return p.startChunkedTransfer(p.st.Conn.OutboundData())
}
// If we don't have a final status from the handshake finished function, stall for time
pst, _ := retry.DoWithData(