diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..3cd2ed320
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/workspace.xml
+# Project exclude paths
+/.
+
diff --git a/.idea/cgrates.iml b/.idea/cgrates.iml
new file mode 100644
index 000000000..d675c01bf
--- /dev/null
+++ b/.idea/cgrates.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 000000000..28a804d89
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..6f72045fc
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..94a25f7f4
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml
new file mode 100644
index 000000000..cb1a78370
--- /dev/null
+++ b/.idea/watcherTasks.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agents/librad.go b/agents/librad.go
index 14a30110a..c6e63aaca 100644
--- a/agents/librad.go
+++ b/agents/librad.go
@@ -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
}
diff --git a/agents/radagent.go b/agents/radagent.go
index ff8710289..201979d4a 100644
--- a/agents/radagent.go
+++ b/agents/radagent.go
@@ -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)
}
}
diff --git a/agents/radagent_it_test.go b/agents/radagent_it_test.go
index a7ea35d50..b4834496d 100644
--- a/agents/radagent_it_test.go
+++ b/agents/radagent_it_test.go
@@ -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)
diff --git a/go.mod b/go.mod
index 4d5a98818..27fc75e47 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index 4349bc91c..11d61bd34 100644
--- a/go.sum
+++ b/go.sum
@@ -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=