From fc5c0e27892bfac432dae91655b4c320a46ecdf1 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 15 May 2025 12:32:27 +0200 Subject: [PATCH] generate MPPE key Signed-off-by: Jens Langhammer --- internal/outpost/radius/eap/handler.go | 7 ++-- internal/outpost/radius/eap/protocol/empty.go | 3 ++ internal/outpost/radius/eap/tls/payload.go | 37 ++++++++++++++++--- internal/outpost/radius/eap/tls/state.go | 1 + 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/internal/outpost/radius/eap/handler.go b/internal/outpost/radius/eap/handler.go index 0e2558ae42..f05ff37324 100644 --- a/internal/outpost/radius/eap/handler.go +++ b/internal/outpost/radius/eap/handler.go @@ -32,12 +32,11 @@ func (p *Packet) Handle(stm StateManager, w radius.ResponseWriter, r *radius.Pac stm.SetEAPState(rst, newState) rres := r.Response(radius.CodeAccessChallenge) - if _, ok := res.Payload.(protocol.EmptyPayload); ok { + if p, ok := res.Payload.(protocol.EmptyPayload); ok { + // This is a bit hacky here res.code = CodeSuccess - rres.Code = radius.CodeAccessAccept res.id -= 1 - rfc2865.UserName_SetString(rres, "foo") - rfc2865.FramedMTU_Set(rres, rfc2865.FramedMTU(1400)) + rres = p.ModifyPacket(rres) } rfc2865.State_SetString(rres, rst) eapEncoded, err := res.Encode() diff --git a/internal/outpost/radius/eap/protocol/empty.go b/internal/outpost/radius/eap/protocol/empty.go index e92e8a6b01..05ee0ffd39 100644 --- a/internal/outpost/radius/eap/protocol/empty.go +++ b/internal/outpost/radius/eap/protocol/empty.go @@ -1,6 +1,9 @@ package protocol +import "layeh.com/radius" + type EmptyPayload struct { + ModifyPacket func(p *radius.Packet) *radius.Packet } func (ep EmptyPayload) Decode(raw []byte) error { diff --git a/internal/outpost/radius/eap/tls/payload.go b/internal/outpost/radius/eap/tls/payload.go index 4c9951ee77..59847d3e3f 100644 --- a/internal/outpost/radius/eap/tls/payload.go +++ b/internal/outpost/radius/eap/tls/payload.go @@ -11,6 +11,8 @@ import ( log "github.com/sirupsen/logrus" "goauthentik.io/internal/outpost/radius/eap/debug" "goauthentik.io/internal/outpost/radius/eap/protocol" + "layeh.com/radius" + "layeh.com/radius/vendors/microsoft" ) const maxChunkSize = 1000 @@ -106,7 +108,7 @@ func (p *Payload) Handle(stt any) (protocol.Payload, *State) { return } log.Debug("TLS: handshake done") - st.HandshakeDone = true + p.handshakeFinished(st) }() } else if len(p.Data) > 0 { log.Debug("TLS: Updating buffer with new TLS data from packet") @@ -135,12 +137,37 @@ func (p *Payload) Handle(stt any) (protocol.Payload, *State) { return p.sendNextChunk(st) } if st.Conn.writer.Len() == 0 && st.HandshakeDone { - return protocol.EmptyPayload{}, st + return protocol.EmptyPayload{ + ModifyPacket: func(p *radius.Packet) *radius.Packet { + p.Code = radius.CodeAccessAccept + microsoft.MSMPPERecvKey_Set(p, st.MPPEKey[:32]) + return p + }, + }, st } - if len(st.Conn.OutboundData()) > 0 { - return p.startChunkedTransfer(st.Conn.OutboundData(), st) + return p.startChunkedTransfer(st.Conn.OutboundData(), st) +} + +func (p *Payload) handshakeFinished(st *State) { + cs := st.TLS.ConnectionState() + label := "client EAP encryption" + var context []byte + switch cs.Version { + case tls.VersionTLS10: + log.Debugf("TLS: Version %d (1.0)", cs.Version) + case tls.VersionTLS11: + log.Debugf("TLS: Version %d (1.1)", cs.Version) + case tls.VersionTLS12: + log.Debugf("TLS: Version %d (1.2)", cs.Version) + case tls.VersionTLS13: + log.Debugf("TLS: Version %d (1.3)", cs.Version) + label = "EXPORTER_EAP_TLS_Key_Material" + context = []byte{13} } - panic("we shouldn't get here") + ksm, err := cs.ExportKeyingMaterial(label, context, 64+64) + log.Debugf("TLS: ksm % x %v", ksm, err) + st.MPPEKey = ksm + st.HandshakeDone = true } func (p *Payload) startChunkedTransfer(data []byte, st *State) (*Payload, *State) { diff --git a/internal/outpost/radius/eap/tls/state.go b/internal/outpost/radius/eap/tls/state.go index 6470d6d3a0..883349a1f8 100644 --- a/internal/outpost/radius/eap/tls/state.go +++ b/internal/outpost/radius/eap/tls/state.go @@ -10,6 +10,7 @@ type State struct { RemainingChunks [][]byte HandshakeDone bool ClientHello *tls.ClientHelloInfo + MPPEKey []byte TotalPayloadSize int TLS *tls.Conn Conn *TLSConnection