@ -2,26 +2,8 @@ package debug
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/google/gopacket"
 | 
			
		||||
	"github.com/google/gopacket/layers"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
	"layeh.com/radius"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func DebugPacket(p *radius.Packet) {
 | 
			
		||||
	log.Debug(p)
 | 
			
		||||
	log.Debug(p.Attributes)
 | 
			
		||||
	n, _ := p.Encode()
 | 
			
		||||
	log.Debug(n)
 | 
			
		||||
	packet := gopacket.NewPacket(n, layers.LayerTypeRADIUS, gopacket.Default)
 | 
			
		||||
	layer := packet.Layer(layers.LayerTypeRADIUS)
 | 
			
		||||
	if layer == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	log.Debug(layer.(*layers.RADIUS))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func FormatBytes(d []byte) string {
 | 
			
		||||
	b := d
 | 
			
		||||
	if len(b) > 32 {
 | 
			
		||||
 | 
			
		||||
@ -1,38 +0,0 @@
 | 
			
		||||
package mschapv2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"layeh.com/radius/rfc2759"
 | 
			
		||||
	"layeh.com/radius/rfc3079"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (p *Payload) checkChapPassword(res *Response) ([]byte, error) {
 | 
			
		||||
	byteUser := []byte("foo")
 | 
			
		||||
	bytePwd := []byte("bar")
 | 
			
		||||
	ntResponse, err := rfc2759.GenerateNTResponse(p.st.Challenge, p.st.PeerChallenge, byteUser, bytePwd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !bytes.Equal(ntResponse, res.NTResponse) {
 | 
			
		||||
		return nil, errors.New("nt response mismatch")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.st.recvKey, err = rfc3079.MakeKey(ntResponse, bytePwd, false)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.st.sendKey, err = rfc3079.MakeKey(ntResponse, bytePwd, true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	authenticatorResponse, err := rfc2759.GenerateAuthenticatorResponse(p.st.Challenge, p.st.PeerChallenge, ntResponse, byteUser, bytePwd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return []byte(authenticatorResponse), nil
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package mschapv2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
@ -115,6 +116,8 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
 | 
			
		||||
		MSCHAPv2ID: rootEap.ID + 1,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	settings := ctx.ProtocolSettings().(Settings)
 | 
			
		||||
 | 
			
		||||
	ctx.Log().Debugf("MSCHAPv2: OpCode: %d", p.OpCode)
 | 
			
		||||
	if p.OpCode == OpResponse {
 | 
			
		||||
		res, err := ParseResponse(p.Response)
 | 
			
		||||
@ -123,21 +126,28 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		p.st.PeerChallenge = res.Challenge
 | 
			
		||||
		auth, err := p.checkChapPassword(res)
 | 
			
		||||
		auth, err := settings.AuthenticateRequest(AuthRequest{
 | 
			
		||||
			Challenge:     p.st.Challenge,
 | 
			
		||||
			PeerChallenge: p.st.PeerChallenge,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.Log().WithError(err).Warning("MSCHAPv2: failed to check password")
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		if !bytes.Equal(auth.NTResponse, res.NTResponse) {
 | 
			
		||||
			ctx.Log().Warning("MSCHAPv2: NT response mismatch")
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Log().Info("MSCHAPv2: Successfully checked password")
 | 
			
		||||
		p.st.Authenticated = true
 | 
			
		||||
		p.st.AuthResponse = auth
 | 
			
		||||
		succ := &SuccessRequest{
 | 
			
		||||
			Payload: &Payload{
 | 
			
		||||
				OpCode: OpSuccess,
 | 
			
		||||
			},
 | 
			
		||||
			Authenticator: auth,
 | 
			
		||||
			Authenticator: []byte(auth.AuthenticatorResponse),
 | 
			
		||||
		}
 | 
			
		||||
		return succ
 | 
			
		||||
	} else if p.OpCode == OpSuccess && p.st.Authenticated {
 | 
			
		||||
	} else if p.OpCode == OpSuccess && p.st.AuthResponse != nil {
 | 
			
		||||
		ep := &peap.ExtensionPayload{
 | 
			
		||||
			AVPs: []peap.ExtensionAVP{
 | 
			
		||||
				{
 | 
			
		||||
@ -152,10 +162,10 @@ func (p *Payload) Handle(ctx protocol.Context) protocol.Payload {
 | 
			
		||||
	} else if p.st.IsProtocolEnded {
 | 
			
		||||
		ctx.EndInnerProtocol(protocol.StatusSuccess, func(r *radius.Packet) *radius.Packet {
 | 
			
		||||
			if len(microsoft.MSMPPERecvKey_Get(r, ctx.Packet().Packet)) < 1 {
 | 
			
		||||
				microsoft.MSMPPERecvKey_Set(r, p.st.recvKey)
 | 
			
		||||
				microsoft.MSMPPERecvKey_Set(r, p.st.AuthResponse.RecvKey)
 | 
			
		||||
			}
 | 
			
		||||
			if len(microsoft.MSMPPESendKey_Get(r, ctx.Packet().Packet)) < 1 {
 | 
			
		||||
				microsoft.MSMPPESendKey_Set(r, p.st.sendKey)
 | 
			
		||||
				microsoft.MSMPPESendKey_Set(r, p.st.AuthResponse.SendKey)
 | 
			
		||||
			}
 | 
			
		||||
			return r
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								internal/outpost/radius/eap/protocol/mschapv2/settings.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								internal/outpost/radius/eap/protocol/mschapv2/settings.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,50 @@
 | 
			
		||||
package mschapv2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"layeh.com/radius/rfc2759"
 | 
			
		||||
	"layeh.com/radius/rfc3079"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Settings struct {
 | 
			
		||||
	AuthenticateRequest func(req AuthRequest) (*AuthResponse, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AuthRequest struct {
 | 
			
		||||
	Challenge     []byte
 | 
			
		||||
	PeerChallenge []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AuthResponse struct {
 | 
			
		||||
	NTResponse            []byte
 | 
			
		||||
	RecvKey               []byte
 | 
			
		||||
	SendKey               []byte
 | 
			
		||||
	AuthenticatorResponse string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DebugStaticCredentials(user, password []byte) func(req AuthRequest) (*AuthResponse, error) {
 | 
			
		||||
	return func(req AuthRequest) (*AuthResponse, error) {
 | 
			
		||||
		res := &AuthResponse{}
 | 
			
		||||
		ntResponse, err := rfc2759.GenerateNTResponse(req.Challenge, req.PeerChallenge, user, password)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		res.NTResponse = ntResponse
 | 
			
		||||
 | 
			
		||||
		res.RecvKey, err = rfc3079.MakeKey(ntResponse, password, false)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res.SendKey, err = rfc3079.MakeKey(ntResponse, password, true)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		res.AuthenticatorResponse, err = rfc2759.GenerateAuthenticatorResponse(req.Challenge, req.PeerChallenge, ntResponse, user, password)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		return res, nil
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -3,8 +3,6 @@ package mschapv2
 | 
			
		||||
type State struct {
 | 
			
		||||
	Challenge       []byte
 | 
			
		||||
	PeerChallenge   []byte
 | 
			
		||||
	Authenticated   bool
 | 
			
		||||
	IsProtocolEnded bool
 | 
			
		||||
	recvKey         []byte
 | 
			
		||||
	sendKey         []byte
 | 
			
		||||
	AuthResponse    *AuthResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user