Update server with mschapv2 auth

This commit is contained in:
TeoV
2020-03-24 18:01:07 +02:00
committed by Dan Christian Bogos
parent 77f0e69ffe
commit d8f50310c8
11 changed files with 225 additions and 38 deletions

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default ignored files
/workspace.xml
# Project exclude paths
/.

17
.idea/cgrates.iml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go">
<buildTags>
<option name="customFlags">
<array>
<option value="integration" />
</array>
</option>
</buildTags>
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/cgrates.iml" filepath="$PROJECT_DIR$/.idea/cgrates.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

8
.idea/watcherTasks.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<enabled-global>
<option value="goimports" />
</enabled-global>
</component>
</project>

View File

@@ -122,7 +122,7 @@ func (pk *radiusDP) RemoteHost() net.Addr {
//radauthReq is used to authorize a request
//if User-Password avp is present use PAP auth
//if CHAP-Password is presented use CHAP auth
func radauthReq(req *radigo.Packet, aReq *AgentRequest) (bool, error) {
func radauthReq(req *radigo.Packet, aReq *AgentRequest, rpl *radigo.Packet) (bool, error) {
// try to get UserPassword from Vars as slice of NMItems
nmItems, err := aReq.Vars.FieldAsInterface([]string{utils.UserPassword})
if err != nil {
@@ -130,16 +130,57 @@ func radauthReq(req *radigo.Packet, aReq *AgentRequest) (bool, error) {
}
userPassAvps := req.AttributesWithName("User-Password", utils.EmptyString)
chapAVPs := req.AttributesWithName("CHAP-Password", utils.EmptyString)
if len(userPassAvps) == 0 && len(chapAVPs) == 0 {
msChallenge := req.AttributesWithName("MS-CHAP-Challenge", "Microsoft")
msResponse := req.AttributesWithName("MS-CHAP-Response", "Microsoft")
if len(userPassAvps) == 0 && len(chapAVPs) == 0 && len(msChallenge) == 0 && len(msResponse) == 0 {
return false, fmt.Errorf("cannot find User-Password or CHAP-Password AVP in request")
}
if len(userPassAvps) != 0 {
switch {
case len(userPassAvps) != 0:
if userPassAvps[0].StringValue != nmItems.([]*config.NMItem)[0].Data {
return false, nil
}
} else {
case len(chapAVPs) != 0:
return radigo.AuthenticateCHAP([]byte(utils.IfaceAsString(nmItems.([]*config.NMItem)[0].Data)),
req.Authenticator[:], chapAVPs[0].RawValue), nil
case len(msChallenge) != 0 && len(msResponse) != 0:
vsaMSResponde := msResponse[0].Value.(*radigo.VSA)
vsaMSChallange := msChallenge[0].Value.(*radigo.VSA)
userName := req.AttributesWithName("User-Name", utils.EmptyString)[0].StringValue
passwordFromAttributes := utils.IfaceAsString(nmItems.([]*config.NMItem)[0].Data)
if len(vsaMSChallange.RawValue) != 16 || len(vsaMSResponde.RawValue) != 50 {
return false, nil
}
ident := vsaMSResponde.RawValue[0]
peerChallenge := vsaMSResponde.RawValue[2:18]
peerResponse := vsaMSResponde.RawValue[26:50]
ntResponse, err := radigo.GenerateNTResponse(vsaMSChallange.RawValue,
peerChallenge, userName, passwordFromAttributes)
if err != nil {
return false, err
}
if len(ntResponse) != len(peerResponse) {
return false, nil
}
for i := range ntResponse {
if ntResponse[i] != peerResponse[i] {
return false, nil
}
}
authenticatorResponse, err := radigo.GenerateAuthenticatorResponse(vsaMSChallange.RawValue, peerChallenge,
ntResponse, userName, passwordFromAttributes)
if err != nil {
return false, err
}
success := make([]byte, 43)
success[0] = ident
copy(success[1:], authenticatorResponse)
// this AVP need to be added to be verified on the client side
rpl.AddAVPWithName("MS-CHAP2-Success", string(success), "Microsoft")
}
return true, nil
}

View File

@@ -87,7 +87,7 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e
ra.filterS, nil, nil)
agReq.Vars.Set([]string{MetaRadReqType}, utils.StringToInterface(MetaRadAuth), false, true)
var lclProcessed bool
if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq); lclProcessed {
if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq, rpl); lclProcessed {
processed = lclProcessed
}
if err != nil || (lclProcessed && !reqProcessor.Flags.GetBool(utils.MetaContinue)) {
@@ -131,7 +131,7 @@ func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err e
config.CgrConfig().GeneralCfg().DefaultTimezone),
ra.filterS, nil, nil)
var lclProcessed bool
if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq); lclProcessed {
if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq, rpl); lclProcessed {
processed = lclProcessed
}
if err != nil || (lclProcessed && !reqProcessor.Flags.GetBool(utils.MetaContinue)) {
@@ -157,7 +157,7 @@ func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err e
// processRequest represents one processor processing the request
func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.RequestProcessor,
agReq *AgentRequest) (processed bool, err error) {
agReq *AgentRequest, rpl *radigo.Packet) (processed bool, err error) {
if pass, err := ra.filterS.Pass(agReq.Tenant,
reqProcessor.Filters, agReq); err != nil || !pass {
return pass, err
@@ -304,9 +304,9 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R
}
case utils.MetaCDRs: // allow this method
case utils.MetaRadauth:
if ok, err := radauthReq(req, agReq); err != nil {
if pass, err := radauthReq(req, agReq, rpl); err != nil {
return false, err
} else if !ok {
} else if !pass {
agReq.CGRReply.Set([]string{utils.Error}, utils.RadauthFailed, false, false)
}
}

View File

@@ -54,6 +54,8 @@ var (
testRAitAuthPAPFail,
testRAitAuthCHAPSuccess,
testRAitAuthCHAPFail,
testRAitAuthMSCHAPV2Success,
testRAitAuthMSCHAPV2Fail,
testRAitAcctStart,
testRAitAcctStop,
testRAitStopCgrEngine,
@@ -62,7 +64,7 @@ var (
// Test start here
func TestRAit(t *testing.T) {
engine.KillEngine(0)
//engine.KillEngine(0)
switch *dbType {
case utils.MetaInternal:
raonfigDIR = "radagent_internal"
@@ -83,6 +85,7 @@ func TestRAit(t *testing.T) {
}
}
/*
func TestRAitDispatcher(t *testing.T) {
if *encoding == utils.MetaGOB {
t.SkipNow()
@@ -99,6 +102,7 @@ func TestRAitDispatcher(t *testing.T) {
engine.KillEngine(100)
isDispatcherActive = false
}
*/
func testRAitInitCfg(t *testing.T) {
raCfgPath = path.Join(*dataDir, "conf", "samples", raonfigDIR)
@@ -339,7 +343,6 @@ func testRAitAuthCHAPFail(t *testing.T) {
if err := authReq.AddAVPWithName("CHAP-Password", "CGRateSPassword2", ""); err != nil {
t.Error(err)
}
authReq.AVPs[1].RawValue = radigo.EncodeCHAPPassword([]byte("CGRateSPassword2"), authReq.Authenticator[:])
if err := authReq.AddAVPWithName("Service-Type", "SIP-Caller-AVPs", ""); err != nil {
t.Error(err)
@@ -373,6 +376,125 @@ func testRAitAuthCHAPFail(t *testing.T) {
}
}
func testRAitAuthMSCHAPV2Success(t *testing.T) {
for _, dictPath := range raCfg.RadiusAgentCfg().ClientDictionaries {
if dictRad, err = radigo.NewDictionaryFromFolderWithRFC2865(dictPath); err != nil {
return
}
}
if raAuthClnt, err = radigo.NewClient("udp", "127.0.0.1:1812", "CGRateS.org", dictRad, 1, nil); err != nil {
t.Fatal(err)
}
authReq := raAuthClnt.NewRequest(radigo.AccessRequest, 1) // emulates Kamailio packet out of radius_load_caller_avps()
if err := authReq.AddAVPWithName("User-Name", "1001", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("MS-CHAP-Challenge", string(authReq.Authenticator[:]), "Microsoft"); err != nil {
t.Error(err)
}
respVal, err := radigo.GenerateClientMSCHAPResponse(authReq.Authenticator, "1001", "CGRateSPassword1")
if err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("MS-CHAP-Response", string(respVal), "Microsoft"); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Service-Type", "SIP-Caller-AVPs", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Called-Station-Id", "1002", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Acct-Session-Id", "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Sip-From-Tag", "51585361", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("NAS-IP-Address", "127.0.0.1", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Event-Timestamp", "1497106115", ""); err != nil {
t.Error(err)
}
reply, err := raAuthClnt.SendRequest(authReq)
if err != nil {
t.Fatal(err)
}
if reply.Code != radigo.AccessAccept {
t.Errorf("Received reply: %+v", utils.ToJSON(reply))
}
if len(reply.AVPs) != 2 { // make sure max duration is received
t.Errorf("Received AVPs: %+v", utils.ToJSON(reply.AVPs))
} else {
for _, avp := range reply.AVPs {
if avp.Number == 26 && len(avp.RawValue) != 49 {
t.Errorf("Unexpected lenght of MS-CHAP2-Success AVP: %+v", len(avp.RawValue))
}
if avp.Number == 225 && !reflect.DeepEqual([]byte("session_max_time#10800"), reply.AVPs[1].RawValue) {
t.Errorf("Received: %s", string(reply.AVPs[0].RawValue))
}
}
}
}
func testRAitAuthMSCHAPV2Fail(t *testing.T) {
for _, dictPath := range raCfg.RadiusAgentCfg().ClientDictionaries {
if dictRad, err = radigo.NewDictionaryFromFolderWithRFC2865(dictPath); err != nil {
return
}
}
if raAuthClnt, err = radigo.NewClient("udp", "127.0.0.1:1812", "CGRateS.org", dictRad, 1, nil); err != nil {
t.Fatal(err)
}
authReq := raAuthClnt.NewRequest(radigo.AccessRequest, 1) // emulates Kamailio packet out of radius_load_caller_avps()
if err := authReq.AddAVPWithName("User-Name", "1001", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("MS-CHAP-Challenge", string(authReq.Authenticator[:]), "Microsoft"); err != nil {
t.Error(err)
}
respVal, err := radigo.GenerateClientMSCHAPResponse(authReq.Authenticator, "1001", "CGRateSPassword2")
if err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("MS-CHAP-Response", string(respVal), "Microsoft"); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Service-Type", "SIP-Caller-AVPs", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Called-Station-Id", "1002", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Acct-Session-Id", "e4921177ab0e3586c37f6a185864b71a@0:0:0:0:0:0:0:0", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Sip-From-Tag", "51585361", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("NAS-IP-Address", "127.0.0.1", ""); err != nil {
t.Error(err)
}
if err := authReq.AddAVPWithName("Event-Timestamp", "1497106115", ""); err != nil {
t.Error(err)
}
reply, err := raAuthClnt.SendRequest(authReq)
if err != nil {
t.Fatal(err)
}
if reply.Code != radigo.AccessReject {
t.Errorf("Received reply: %+v", reply)
}
if len(reply.AVPs) != 1 { // make sure max duration is received
t.Errorf("Received AVPs: %+v", reply.AVPs)
} else if !reflect.DeepEqual(utils.RadauthFailed, string(reply.AVPs[0].RawValue)) {
t.Errorf("Received: %s", string(reply.AVPs[0].RawValue))
}
}
func testRAitAcctStart(t *testing.T) {
if raAcctClnt, err = radigo.NewClient("udp", "127.0.0.1:1813", "CGRateS.org", dictRad, 1, nil); err != nil {
t.Fatal(err)

2
go.mod
View File

@@ -2,7 +2,7 @@ module github.com/cgrates/cgrates
go 1.14
replace github.com/cgrates/radigo => ../radigo
// replace github.com/cgrates/radigo => ../radigo
// replace github.com/cgrates/rpcclient => ../rpcclient

26
go.sum
View File

@@ -55,38 +55,12 @@ github.com/cgrates/aringo v0.0.0-20181115151919-f996da7890ea h1:KvikDlQoQdSWBc2E
github.com/cgrates/aringo v0.0.0-20181115151919-f996da7890ea/go.mod h1:rGqp3Xbv+cXkzlJQ12SEz7a0wx5k7wVsVPAMFszuyCA=
github.com/cgrates/fsock v0.0.0-20190623100231-317895b42f1a h1:GTXhk4FSzdyLkJgK5J8l2g1MR6nMnl0KPZKoLlLuEk8=
github.com/cgrates/fsock v0.0.0-20190623100231-317895b42f1a/go.mod h1:uWcTZ01eKJdWcoYBhsEXKgSlO6Vv8wT9qcR5JeJovBs=
github.com/cgrates/kamevapi v0.0.0-20190605144325-ec679e017654 h1:D2NqOOYKha71Ab6WfZBCJpWZOyr8BPpAm3q5a1OWFBI=
github.com/cgrates/kamevapi v0.0.0-20190605144325-ec679e017654/go.mod h1:pgHqPlPcEDIQbbs9wyBk7YZTcaVdxMqf3v04XU+mngI=
github.com/cgrates/kamevapi v0.0.0-20191001070356-51d06bab2926 h1:eb9F8blPHqBnAyLkW5U0eTTV0/j2tMrVTIBVxcm8bXY=
github.com/cgrates/kamevapi v0.0.0-20191001070356-51d06bab2926/go.mod h1:pgHqPlPcEDIQbbs9wyBk7YZTcaVdxMqf3v04XU+mngI=
github.com/cgrates/kamevapi v0.0.0-20191001125829-7dbc3ad58817 h1:1Tdv6H/usqmkQVeQbd+x87L5xo6DFmbYpbI00qfrWGw=
github.com/cgrates/kamevapi v0.0.0-20191001125829-7dbc3ad58817/go.mod h1:pgHqPlPcEDIQbbs9wyBk7YZTcaVdxMqf3v04XU+mngI=
github.com/cgrates/ltcache v0.0.0-20181016092649-92fb7fa77cca h1:Ejj4m0Ccl8dMMVnoHk4nQMlbR3w24llqQDy66DO9E0A=
github.com/cgrates/ltcache v0.0.0-20181016092649-92fb7fa77cca/go.mod h1:q7c996DUu8OrJRnewVSQzM+y/bRcxZAHoo+zCD8bFBo=
github.com/cgrates/radigo v0.0.0-20181207143118-e5c8f3272ccc h1:vOvPAyI9pNhUM5k/Wc3mYvwmGpDrMg41BMkz4AW1wfg=
github.com/cgrates/radigo v0.0.0-20181207143118-e5c8f3272ccc/go.mod h1:cMU/VXvC9YH2kXbhpgnkppYRjpqS8XgkKb8dI8HpU1I=
github.com/cgrates/radigo v0.0.0-20200101201328-55baf0f8c432 h1:JlaJ1vGsR9EmvamLffFoW5AILBeaoCOhuLLANIUSgpk=
github.com/cgrates/radigo v0.0.0-20200101201328-55baf0f8c432/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/radigo v0.0.0-20200102144505-ef98592ff532 h1:Lyuz+ROAx4d4ep5HKeiBFFC2OaK/yyJ5KTFRquFOyrQ=
github.com/cgrates/radigo v0.0.0-20200102144505-ef98592ff532/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/radigo v0.0.0-20200306160903-17b28bb0e1bb h1:LnoYQFohxLduxNFZHucwM8OKOjw59Gr78zk9y5XKhbw=
github.com/cgrates/radigo v0.0.0-20200306160903-17b28bb0e1bb/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/radigo v0.0.0-20200309151443-bb470a5a5c8d h1:4dDI8QG+rkQTNWwsRmeAQWLaofRvVRd3JgG/h4o9VG0=
github.com/cgrates/radigo v0.0.0-20200309151443-bb470a5a5c8d/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/radigo v0.0.0-20200318092814-07da25249ae6 h1:NLRfnSh1TGtCrgxVnpaSOEiwprmf/sQ+aOTM1kiEvaE=
github.com/cgrates/radigo v0.0.0-20200318092814-07da25249ae6/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/radigo v0.0.0-20200321121249-9e416fdf1479 h1:UNareDs0BcycjiSy2ltRlsiaeoohDdt9OQOg55ak5Jc=
github.com/cgrates/radigo v0.0.0-20200321121249-9e416fdf1479/go.mod h1:mTCzHAYfgZlRe0HorDz+jy2JTrNvNuKkHBAUjDZBWq8=
github.com/cgrates/rpcclient v0.0.0-20190505150825-8fcc68b2c38b h1:GC+/hEDN/2Frh8Tjkf7u1XFxj0Z2XtwjBxj0OH6Mzhw=
github.com/cgrates/rpcclient v0.0.0-20190505150825-8fcc68b2c38b/go.mod h1:Jy5Lv0y57OlxlNATKrkyAxgftYLHqXuxONgd4qsAC1U=
github.com/cgrates/rpcclient v0.0.0-20191115092211-732f09b356e3 h1:Hr038ZfPZz87OKLV4pRSzf3U06lZ8zjl/cXpwrv7hCM=
github.com/cgrates/rpcclient v0.0.0-20191115092211-732f09b356e3/go.mod h1:Jy5Lv0y57OlxlNATKrkyAxgftYLHqXuxONgd4qsAC1U=
github.com/cgrates/rpcclient v0.0.0-20191209100218-70f91dc30ac6 h1:g1LZmbYvqYkGAxM4/bNfTcBooCFf0lK2mgrp3yZERL0=
github.com/cgrates/rpcclient v0.0.0-20191209100218-70f91dc30ac6/go.mod h1:xXLqAKVvcdWeDYwHJYwDgAI3ZOg5LZYxzb72kLjsLZU=
github.com/cgrates/rpcclient v0.0.0-20191212101551-ff9c136f66a7 h1:szJPaMz/49gP0X6M1DhjhImDP3rLN8ul7rio2tzorNc=
github.com/cgrates/rpcclient v0.0.0-20191212101551-ff9c136f66a7/go.mod h1:xXLqAKVvcdWeDYwHJYwDgAI3ZOg5LZYxzb72kLjsLZU=
github.com/cgrates/rpcclient v0.0.0-20200107085551-6be8ad1df845 h1:bzvXBBqUqf2q4nW8RAwy+BXwxzlxFSGUAkW8W0TNLk8=
github.com/cgrates/rpcclient v0.0.0-20200107085551-6be8ad1df845/go.mod h1:xXLqAKVvcdWeDYwHJYwDgAI3ZOg5LZYxzb72kLjsLZU=
github.com/cgrates/rpcclient v0.0.0-20200107134035-188454eb71b3 h1:esWCSaLD2j+zfK9JpyPXFSe3c97MQFhfKp9jDiss1mU=
github.com/cgrates/rpcclient v0.0.0-20200107134035-188454eb71b3/go.mod h1:xXLqAKVvcdWeDYwHJYwDgAI3ZOg5LZYxzb72kLjsLZU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=