diff --git a/internal/outpost/radius/eap/handler.go b/internal/outpost/radius/eap/handler.go index 2f965d719f..0d856e2bf7 100644 --- a/internal/outpost/radius/eap/handler.go +++ b/internal/outpost/radius/eap/handler.go @@ -35,6 +35,8 @@ func (p *Packet) HandleRadiusPacket(w radius.ResponseWriter, r *radius.Request) if err == nil { rres = p.endModifier(rres) switch rp.code { + case CodeRequest: + rres.Code = radius.CodeAccessChallenge case CodeFailure: rres.Code = radius.CodeAccessReject case CodeSuccess: @@ -81,13 +83,18 @@ func (p *Packet) handleInner(r *radius.Request) (*Packet, error) { }, err } - if _, ok := p.Payload.(*legacy_nak.Payload); ok { - log.Debug("EAP: received NAK, trying next protocol") + next := func() (*Packet, error) { st.ProtocolIndex += 1 p.stm.SetEAPState(p.state, st) return p.handleInner(r) } + if _, ok := p.Payload.(*legacy_nak.Payload); ok { + log.Debug("EAP: received NAK, trying next protocol") + p.Payload = nil + return next() + } + np, _ := emptyPayload(p.stm, nextChallengeToOffer) ctx := &context{ @@ -96,6 +103,10 @@ func (p *Packet) handleInner(r *radius.Request) (*Packet, error) { log: log.WithField("type", fmt.Sprintf("%T", np)), settings: p.stm.GetEAPSettings().ProtocolSettings[np.Type()], } + if !np.Offerable() { + ctx.log.Debug("EAP: protocol not offerable, skipping") + return next() + } ctx.log.Debug("EAP: Passing to protocol") res := p.GetChallengeForType(ctx, np) @@ -115,9 +126,7 @@ func (p *Packet) handleInner(r *radius.Request) (*Packet, error) { res.id -= 1 case protocol.StatusNextProtocol: ctx.log.Debug("EAP: Protocol ended, starting next protocol") - st.ProtocolIndex += 1 - p.stm.SetEAPState(p.state, st) - return p.handleInner(r) + return next() case protocol.StatusUnknown: } return res, nil diff --git a/internal/outpost/radius/eap/peap/payload.go b/internal/outpost/radius/eap/peap/payload.go new file mode 100644 index 0000000000..eade000598 --- /dev/null +++ b/internal/outpost/radius/eap/peap/payload.go @@ -0,0 +1,42 @@ +package peap + +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/tls" +) + +const TypePEAP protocol.Type = 25 + +func Protocol() protocol.Payload { + return &tls.Payload{ + Inner: &Payload{}, + } +} + +type Payload struct { +} + +func (p *Payload) Type() protocol.Type { + return TypePEAP +} + +func (p *Payload) Decode(raw []byte) error { + log.WithField("raw", debug.FormatBytes(raw)).Debug("PEAP: Decode") + return nil +} + +func (p *Payload) Encode() ([]byte, error) { + log.Debug("PEAP: Encode") + return []byte{}, nil +} + +func (p *Payload) Handle(ctx protocol.Context) protocol.Payload { + log.Debug("PEAP: Handle") + return &Payload{} +} + +func (p *Payload) Offerable() bool { + return true +} diff --git a/internal/outpost/radius/eap/tls/inner.go b/internal/outpost/radius/eap/tls/inner.go new file mode 100644 index 0000000000..361458035d --- /dev/null +++ b/internal/outpost/radius/eap/tls/inner.go @@ -0,0 +1,21 @@ +package tls + +import ( + "goauthentik.io/internal/outpost/radius/eap/protocol" +) + +func (p *Payload) innerHandler(ctx protocol.Context) *Payload { + // 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 + } + pl := p.Inner.Handle(ctx) + enc, err := pl.Encode() + return &Payload{ + Data: enc, + } +} diff --git a/internal/outpost/radius/eap/tls/payload.go b/internal/outpost/radius/eap/tls/payload.go index a24c44dc5e..107f05ff3b 100644 --- a/internal/outpost/radius/eap/tls/payload.go +++ b/internal/outpost/radius/eap/tls/payload.go @@ -30,10 +30,14 @@ type Payload struct { Length uint32 Data []byte - st *State + st *State + Inner protocol.Payload } func (p *Payload) Type() protocol.Type { + if p.Inner != nil { + return p.Inner.Type() + } return TypeTLS } @@ -118,6 +122,10 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload { } if p.st.Conn.writer.Len() == 0 && p.st.HandshakeDone { defer p.st.ContextCancel() + if p.Inner != nil { + ctx.Log().Debug("TLS: Handshake is done, delegating to inner protocol") + return p.innerHandler(ctx) + } // If we don't have a final status from the handshake finished function, stall for time pst, _ := retry.DoWithData( func() (protocol.Status, error) { @@ -153,6 +161,7 @@ func (p *Payload) tlsInit(ctx protocol.Context) { return nil, nil } p.st.TLS = tls.Server(p.st.Conn, cfg) + p.st.TLS.SetDeadline(time.Now().Add(staleConnectionTimeout * time.Second)) go func() { err := p.st.TLS.HandshakeContext(p.st.Context) if err != nil { @@ -188,7 +197,9 @@ func (p *Payload) tlsHandshakeFinished(ctx protocol.Context) { ctx.Log().Debugf("TLS: ksm % x %v", ksm, err) p.st.MPPEKey = ksm p.st.HandshakeDone = true - p.st.FinalStatus = ctx.ProtocolSettings().(Settings).HandshakeSuccessful(ctx, cs.PeerCertificates) + if p.Inner == nil { + p.st.FinalStatus = ctx.ProtocolSettings().(Settings).HandshakeSuccessful(ctx, cs.PeerCertificates) + } } func (p *Payload) startChunkedTransfer(data []byte) *Payload { diff --git a/internal/outpost/radius/handle_access_request.go b/internal/outpost/radius/handle_access_request.go index 9fe2cebc95..db3881027d 100644 --- a/internal/outpost/radius/handle_access_request.go +++ b/internal/outpost/radius/handle_access_request.go @@ -14,6 +14,7 @@ import ( "goauthentik.io/internal/outpost/radius/eap" "goauthentik.io/internal/outpost/radius/eap/identity" "goauthentik.io/internal/outpost/radius/eap/legacy_nak" + "goauthentik.io/internal/outpost/radius/eap/peap" "goauthentik.io/internal/outpost/radius/eap/protocol" "goauthentik.io/internal/outpost/radius/eap/tls" "goauthentik.io/internal/outpost/radius/metrics" @@ -150,9 +151,10 @@ func (pi *ProviderInstance) GetEAPSettings() eap.Settings { } return eap.Settings{ - Protocols: append(protocols, tls.Protocol), + Protocols: append(protocols, tls.Protocol, peap.Protocol), ProtocolPriority: []protocol.Type{ tls.TypeTLS, + peap.TypePEAP, }, ProtocolSettings: map[protocol.Type]interface{}{ tls.TypeTLS: tls.Settings{ @@ -187,6 +189,11 @@ func (pi *ProviderInstance) GetEAPSettings() eap.Settings { } }, }, + peap.TypePEAP: tls.Settings{ + Config: &ttls.Config{ + Certificates: []ttls.Certificate{*cert}, + }, + }, }, } }