working PEAP decode
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -59,7 +59,7 @@ func (p *Packet) HandleRadiusPacket(w radius.ResponseWriter, r *radius.Request)
|
||||
sendErrorResponse(w, r)
|
||||
return
|
||||
}
|
||||
log.WithField("length", len(eapEncoded)).WithField("type", fmt.Sprintf("%T", rp.eap.Payload)).Debug("EAP: encapsulated challenge")
|
||||
log.WithField("length", len(eapEncoded)).WithField("type", fmt.Sprintf("%T", rp.eap.Payload)).Debug("Root-EAP: encapsulated challenge")
|
||||
rfc2869.EAPMessage_Set(rres, eapEncoded)
|
||||
err = p.setMessageAuthenticator(rres)
|
||||
if err != nil {
|
||||
@ -76,7 +76,7 @@ func (p *Packet) HandleRadiusPacket(w radius.ResponseWriter, r *radius.Request)
|
||||
func (p *Packet) handleInner(r *radius.Request) (*eap.Payload, error) {
|
||||
st := p.stm.GetEAPState(p.state)
|
||||
if st == nil {
|
||||
log.Debug("EAP: blank state")
|
||||
log.Debug("Root-EAP: blank state")
|
||||
st = BlankState(p.stm.GetEAPSettings())
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ func (p *Packet) handleInner(r *radius.Request) (*eap.Payload, error) {
|
||||
}
|
||||
|
||||
if _, ok := p.eap.Payload.(*legacy_nak.Payload); ok {
|
||||
log.Debug("EAP: received NAK, trying next protocol")
|
||||
log.Debug("Root-EAP: received NAK, trying next protocol")
|
||||
p.eap.Payload = nil
|
||||
return next()
|
||||
}
|
||||
@ -111,10 +111,10 @@ func (p *Packet) handleInner(r *radius.Request) (*eap.Payload, error) {
|
||||
settings: p.stm.GetEAPSettings().ProtocolSettings[t],
|
||||
}
|
||||
if !np.Offerable() {
|
||||
ctx.log.Debug("EAP: protocol not offerable, skipping")
|
||||
ctx.log.Debug("Root-EAP: protocol not offerable, skipping")
|
||||
return next()
|
||||
}
|
||||
ctx.log.Debug("EAP: Passing to protocol")
|
||||
ctx.log.Debug("Root-EAP: Passing to protocol")
|
||||
|
||||
res := p.GetChallengeForType(ctx, np, t)
|
||||
p.stm.SetEAPState(p.state, st)
|
||||
@ -131,7 +131,7 @@ func (p *Packet) handleInner(r *radius.Request) (*eap.Payload, error) {
|
||||
res.Code = protocol.CodeFailure
|
||||
res.ID -= 1
|
||||
case protocol.StatusNextProtocol:
|
||||
ctx.log.Debug("EAP: Protocol ended, starting next protocol")
|
||||
ctx.log.Debug("Root-EAP: Protocol ended, starting next protocol")
|
||||
return next()
|
||||
case protocol.StatusUnknown:
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package eap
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@ -38,16 +37,16 @@ func (packet *Payload) Decode(raw []byte) error {
|
||||
packet.ID = raw[1]
|
||||
packet.Length = binary.BigEndian.Uint16(raw[2:])
|
||||
if packet.Length != uint16(len(raw)) {
|
||||
return errors.New("mismatched packet length")
|
||||
return fmt.Errorf("mismatched packet length; got %d, expected %d", packet.Length, uint16(len(raw)))
|
||||
}
|
||||
if len(raw) > 4 && (packet.Code == protocol.CodeRequest || packet.Code == protocol.CodeResponse) {
|
||||
packet.MsgType = protocol.Type(raw[4])
|
||||
}
|
||||
log.WithField("raw", debug.FormatBytes(raw)).WithField("payload", fmt.Sprintf("%T", packet.Payload)).Trace("EAP: decode raw")
|
||||
packet.RawPayload = raw[5:]
|
||||
if packet.Payload == nil {
|
||||
return nil
|
||||
}
|
||||
log.WithField("raw", debug.FormatBytes(raw)).WithField("payload", fmt.Sprintf("%T", packet.Payload)).Trace("EAP: decode raw")
|
||||
err := packet.Payload.Decode(raw[5:])
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package peap
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"goauthentik.io/internal/outpost/radius/eap/debug"
|
||||
"goauthentik.io/internal/outpost/radius/eap/protocol"
|
||||
@ -45,6 +47,28 @@ func (p *Payload) Encode() ([]byte, error) {
|
||||
return p.eap.Encode()
|
||||
}
|
||||
|
||||
// Inner EAP packets in PEAP may not include the header, hence we need a custom decoder
|
||||
// https://datatracker.ietf.org/doc/html/draft-kamath-pppext-peapv0-00.txt#section-1.1
|
||||
func (p *Payload) eapInnerDecode(ctx protocol.Context) (*eap.Payload, error) {
|
||||
ep := &eap.Payload{}
|
||||
rootEap := ctx.RootPayload().(*eap.Payload)
|
||||
fixedRaw := []byte{
|
||||
byte(rootEap.Code),
|
||||
rootEap.ID,
|
||||
// 2 byte space for length
|
||||
0,
|
||||
0,
|
||||
}
|
||||
fullLength := len(p.raw) + len(fixedRaw)
|
||||
binary.BigEndian.PutUint16(fixedRaw[2:], uint16(fullLength))
|
||||
fixedRaw = append(fixedRaw, p.raw...)
|
||||
err := ep.Decode(fixedRaw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ep, nil
|
||||
}
|
||||
|
||||
func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
|
||||
defer func() {
|
||||
ctx.SetProtocolState(TypePEAP, p.st)
|
||||
@ -64,13 +88,15 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
|
||||
}
|
||||
p.st = ctx.GetProtocolState(TypePEAP).(*State)
|
||||
|
||||
ep := &eap.Payload{}
|
||||
err := ep.Decode(p.raw)
|
||||
ep, err := p.eapInnerDecode(ctx)
|
||||
if err != nil {
|
||||
ctx.Log().WithError(err).Warning("PEAP: failed to decode inner EAP")
|
||||
return &Payload{}
|
||||
return &eap.Payload{
|
||||
Code: protocol.CodeFailure,
|
||||
ID: rootEap.ID + 1,
|
||||
}
|
||||
}
|
||||
return &Payload{}
|
||||
return ep
|
||||
}
|
||||
|
||||
func (p *Payload) Offerable() bool {
|
||||
|
||||
@ -5,9 +5,15 @@ import (
|
||||
)
|
||||
|
||||
func (p *Payload) innerHandler(ctx protocol.Context) {
|
||||
// p.st.TLS.read
|
||||
// d, _ := io.ReadAll(p.st.TLS)
|
||||
err := p.Inner.Decode([]byte{})
|
||||
d := make([]byte, 1024)
|
||||
if !ctx.IsProtocolStart(p.Inner.Type()) {
|
||||
ctx.Log().Debug("TLS: Reading from TLS for inner protocol")
|
||||
_, err := p.st.TLS.Read(d)
|
||||
if err != nil {
|
||||
ctx.Log().WithError(err).Warning("TLS: Failed to read from TLS connection")
|
||||
}
|
||||
}
|
||||
err := p.Inner.Decode(d)
|
||||
if err != nil {
|
||||
ctx.Log().WithError(err).Warning("TLS: failed to decode inner protocol")
|
||||
ctx.EndInnerProtocol(protocol.StatusError, nil)
|
||||
@ -16,14 +22,14 @@ func (p *Payload) innerHandler(ctx protocol.Context) {
|
||||
pl := p.Inner.Handle(ctx)
|
||||
enc, err := pl.Encode()
|
||||
if err != nil {
|
||||
ctx.Log().WithError(err).Warning("failed to encode inner protocol")
|
||||
ctx.Log().WithError(err).Warning("TLS: failed to encode inner protocol")
|
||||
ctx.EndInnerProtocol(protocol.StatusError, nil)
|
||||
return
|
||||
}
|
||||
// p.st.Conn.expectedWriterByteCount = len(enc)
|
||||
_, err = p.st.TLS.Write(enc)
|
||||
if err != nil {
|
||||
ctx.Log().WithError(err).Warning("failed to write to TLS")
|
||||
ctx.Log().WithError(err).Warning("TLS: failed to write to TLS")
|
||||
ctx.EndInnerProtocol(protocol.StatusError, nil)
|
||||
return
|
||||
}
|
||||
// return &Payload{
|
||||
// Data: enc,
|
||||
// }
|
||||
}
|
||||
|
||||
@ -36,9 +36,6 @@ type Payload struct {
|
||||
}
|
||||
|
||||
func (p *Payload) Type() protocol.Type {
|
||||
// if p.inner != nil {
|
||||
// return p.inner.Type()
|
||||
// }
|
||||
return TypeTLS
|
||||
}
|
||||
|
||||
@ -109,7 +106,7 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
|
||||
p.st.Conn.expectedWriterByteCount = 0
|
||||
}
|
||||
p.st.Conn.UpdateData(p.Data)
|
||||
if !p.st.Conn.NeedsMoreData() {
|
||||
if !p.st.Conn.NeedsMoreData() && !p.st.HandshakeDone {
|
||||
// Wait for outbound data to be available
|
||||
p.st.Conn.OutboundData()
|
||||
}
|
||||
@ -126,12 +123,12 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
|
||||
return p.sendNextChunk()
|
||||
}
|
||||
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")
|
||||
p.innerHandler(ctx)
|
||||
return p.startChunkedTransfer(p.st.Conn.OutboundData())
|
||||
}
|
||||
defer p.st.ContextCancel()
|
||||
// If we don't have a final status from the handshake finished function, stall for time
|
||||
pst, _ := retry.DoWithData(
|
||||
func() (protocol.Status, error) {
|
||||
|
||||
Reference in New Issue
Block a user