github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgRadius/Auth.go (about) 1 package kmgRadius 2 3 import ( 4 "crypto/rand" 5 "fmt" 6 7 . "github.com/bronze1man/kmg/kmgErr" 8 "github.com/bronze1man/kmg/kmgLog" 9 "github.com/bronze1man/kmg/kmgRand" 10 "github.com/bronze1man/kmg/third/kmgRadius/MSCHAPV2" 11 "github.com/bronze1man/kmg/third/kmgRadius/eap" 12 ) 13 14 // 目前支持pap和mschapv2认证方式 15 func (p *server) radiusAccess(request *Packet) *Packet { 16 kmgLog.Log("Radius", "Access Request", request.ToStringMap()) 17 npac := request.Reply() 18 19 username := request.GetUsername() 20 password := request.GetPassword() 21 if username == "" { 22 //不支持的认证方式,或者包格式错误 23 npac.AVPs = append(npac.AVPs, &StringAVP{Type: AVPTypeReplyMessage, Value: "need username"}) 24 npac.Code = CodeAccessReject 25 LogError(fmt.Errorf("[kmgRadius.radiusAccess] need username or auth method not support")) 26 return npac 27 } 28 AuthPassword, exist := p.handler.Auth(username) 29 if !exist { 30 LogError(fmt.Errorf("[kmgRadius.radiusAccess] username [%s] not exist or do not have any transfer", username)) 31 npac.Code = CodeAccessReject 32 return npac 33 } 34 //简单认证方式 pap 35 if password != "" { 36 if AuthPassword != password { 37 LogError(fmt.Errorf("[kmgRadius.radiusAccess] username [%s] password not match", username)) 38 npac.Code = CodeAccessReject 39 return npac 40 } 41 npac.Code = CodeAccessAccept 42 return npac 43 } 44 //复杂认证方式 45 //如果没有输入密码,要求用户输入密码(遗留代码,应该是之前的bug导致的) 46 e := request.GetEAPMessage() 47 if e != nil { 48 //第一次请求,eapCode应该是 Response 49 // mschapv2 step 1 50 switch e.Header().Type { 51 case eap.TypeIdentity, eap.TypeLegacyNak: 52 npac.Code = CodeAccessChallenge 53 mschapV2Challenge := [16]byte{} 54 _, err := rand.Read(mschapV2Challenge[:]) 55 if err != nil { 56 panic(err) 57 } 58 sessionId := kmgRand.MustCryptoRandToAlphaNum(18) 59 npac.SetState([]byte(sessionId)) 60 61 p.mschapMap[sessionId] = mschapStatus{ 62 Challenge: mschapV2Challenge, 63 } 64 npac.AddAVP(&EapAVP{ 65 Value: &eap.MSCHAPV2Packet{ 66 PacketHeader: eap.PacketHeader{ 67 Code: eap.CodeRequest, 68 Identifier: e.Header().Identifier, 69 Type: eap.TypeMSCHAPV2, 70 }, 71 MSCHAPV2: &MSCHAPV2.ChallengePacket{ 72 Identifier: e.Header().Identifier, 73 Challenge: mschapV2Challenge, 74 Name: username, 75 }, 76 }, 77 }) 78 return npac 79 //TODO process next step read Response packet and write Success Request packet 80 // reference http://tools.ietf.org/id/draft-kamath-pppext-eap-mschapv2-01.txt 81 case eap.TypeMSCHAPV2: 82 // mschapv2 step 3 and step 5 83 if e.Header().Code != eap.CodeResponse { 84 npac.Code = CodeAccessReject 85 LogError(fmt.Errorf("MSCHAPV2 step 3 fail! 1 eap.Code[%s]!=radius.EapCodeResponse", e.Header().Code)) 86 return npac 87 } 88 mschapv2I := e.(*eap.MSCHAPV2Packet).MSCHAPV2 89 switch mschapv2I.OpCode() { 90 case MSCHAPV2.OpCodeResponse: 91 state := request.GetState() 92 //step 3 93 status, ok := p.mschapMap[string(state)] 94 if !ok { 95 npac.Code = CodeAccessReject 96 LogError(fmt.Errorf("MSCHAPV2 step 3 fail! 3 mschapStatus not found state:%s", state)) 97 return npac 98 } 99 status.NTResponse = mschapv2I.(*MSCHAPV2.ResponsePacket).NTResponse 100 p.mschapMap[string(state)] = status 101 successPacket := MSCHAPV2.ReplySuccessPacket(&MSCHAPV2.ReplySuccessPacketRequest{ 102 AuthenticatorChallenge: status.Challenge, 103 Response: mschapv2I.(*MSCHAPV2.ResponsePacket), 104 Username: []byte(username), 105 Password: []byte(AuthPassword), 106 Message: "success", 107 }) 108 npac.AddAVP(&EapAVP{ 109 Value: &eap.MSCHAPV2Packet{ 110 PacketHeader: eap.PacketHeader{ 111 Code: eap.CodeRequest, 112 Identifier: e.Header().Identifier, 113 Type: eap.TypeMSCHAPV2, 114 }, 115 MSCHAPV2: successPacket, 116 }, 117 }) 118 npac.Code = CodeAccessChallenge 119 return npac 120 case MSCHAPV2.OpCodeSuccess: 121 //step 5 122 // reference http://www.ietf.org/rfc/rfc3079.txt 123 state := request.GetState() 124 //step 3 125 status, ok := p.mschapMap[string(state)] 126 if !ok { 127 npac.Code = CodeAccessReject 128 LogError(fmt.Errorf("MSCHAPV2 step 5 fail! 5 mschapStatus not found state:%#v", state)) 129 return npac 130 } 131 132 npac.AddAVP(&EapAVP{ 133 Value: &eap.SimplePacket{ 134 PacketHeader: eap.PacketHeader{ 135 Code: eap.CodeSuccess, 136 Identifier: e.Header().Identifier, 137 }, 138 }, 139 }) 140 npac.AddAVP(&StringAVP{ 141 Type: AVPTypeUserName, 142 Value: username, 143 }) 144 //MS-MPPE-Encryption-Policy: Encryption-Allowed (1) 145 npac.AddAVP(&BinaryAVP{ 146 Type: AVPTypeVendorSpecific, 147 Value: []byte{0x00, 0x00, 0x01, 0x37, 0x07, 0x06, 0, 0, 0, 1}, 148 }) 149 //MS-MPPE-Encryption-Types: RC4-40-128 (6) 150 npac.AddAVP(&BinaryAVP{ 151 Type: AVPTypeVendorSpecific, 152 Value: []byte{0x00, 0x00, 0x01, 0x37, 0x08, 0x06, 0, 0, 0, 6}, 153 }) 154 sendkey, recvKey := MSCHAPV2.MsCHAPV2GetSendAndRecvKey([]byte(AuthPassword), status.NTResponse) 155 npac.AddAVP(&VendorSpecificAVP{ 156 Value: NewMSMPPESendOrRecvKeyVSA(request, VendorTypeMSMPPESendKey, sendkey), 157 }) 158 npac.AddAVP(&VendorSpecificAVP{ 159 Value: NewMSMPPESendOrRecvKeyVSA(request, VendorTypeMSMPPERecvKey, recvKey), 160 }) 161 npac.Code = CodeAccessAccept 162 npac.DeleteOneType(AVPTypeState) 163 return npac 164 default: 165 npac.Code = CodeAccessReject 166 LogError(fmt.Errorf("MSCHAPV2 step 3 and 5 fail! 2.5 mschapv2I.OpCode()[%s]!= MSCHAPV2.OpCodeResponse", 167 mschapv2I.OpCode())) 168 return npac 169 } 170 default: 171 npac.Code = CodeAccessReject 172 LogError(fmt.Errorf("MSCHAPV2 eap fail! 4")) 173 return npac 174 } 175 } 176 //不支持的认证方式,或者包格式错误 177 npac.AVPs = append(npac.AVPs, &StringAVP{Type: AVPTypeReplyMessage, Value: "need password"}) 178 npac.Code = CodeAccessReject 179 LogError(fmt.Errorf("[kmgRadius.radiusAccess] username[%s] need password or auth method not support", username)) 180 return npac 181 }