github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgRadius/MSCHAPV2/packet.go (about) 1 package MSCHAPV2 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "fmt" 8 "strconv" 9 ) 10 11 type Packet interface { 12 String() string 13 OpCode() OpCode 14 Encode() (b []byte) 15 } 16 17 func Decode(b []byte) (p Packet, err error) { 18 if len(b) == 1 { 19 //eap - mschapv2 的一种特殊情况,只有opcode,其他啥也没有 20 return &SimplePacket{ 21 Code: OpCode(b[0]), 22 }, nil 23 } 24 if len(b) < 4 { 25 return nil, fmt.Errorf("[MSCHAPV2.Decode] protocol error 1, len(b)[%d] < 2", len(b)) 26 } 27 code := OpCode(b[0]) 28 Identifier := uint8(b[1]) 29 switch code { 30 case OpCodeChallenge: 31 if len(b) < 21 { 32 return nil, fmt.Errorf("[MsChapV2PacketFromEap] protocol error 2 Challenge packet len is less than 21 ") 33 } 34 resp := &ChallengePacket{} 35 copy(resp.Challenge[:], b[5:21]) 36 resp.Name = string(b[21:]) 37 resp.Identifier = Identifier 38 return resp, nil 39 case OpCodeResponse: 40 if len(b) < 53 { 41 return nil, fmt.Errorf("[MsChapV2PacketFromEap] protocol error 3 Response packet len is less than 53 ") 42 } 43 resp := &ResponsePacket{} 44 copy(resp.PeerChallenge[:], b[5:21]) 45 copy(resp.NTResponse[:], b[29:53]) 46 resp.Name = string(b[54:]) 47 resp.Identifier = Identifier 48 return resp, nil 49 case OpCodeSuccess: 50 resp := &SuccessPacket{} 51 hex.Decode(resp.Auth[:], b[6:46]) 52 resp.Message = string(b[49:]) 53 resp.Identifier = Identifier 54 return resp, nil 55 default: 56 return nil, fmt.Errorf("[MsChapV2PacketFromEap] can not parse opcode:%s", p.OpCode) 57 } 58 return p, nil 59 } 60 61 type OpCode uint8 62 63 const ( 64 OpCodeChallenge OpCode = 1 65 OpCodeResponse OpCode = 2 66 OpCodeSuccess OpCode = 3 67 OpCodeFailure OpCode = 4 68 OpCodeChangePassword OpCode = 7 69 ) 70 71 func (c OpCode) String() string { 72 switch c { 73 case OpCodeChallenge: 74 return "Challenge" 75 case OpCodeResponse: 76 return "Response" 77 case OpCodeSuccess: 78 return "Success" 79 case OpCodeFailure: 80 return "Failure" 81 case OpCodeChangePassword: 82 return "ChangePassword" 83 default: 84 return "unknow OpCode " + strconv.Itoa(int(c)) 85 } 86 } 87 88 type ChallengePacket struct { 89 Identifier uint8 90 Challenge [16]byte 91 Name string 92 } 93 94 func (p *ChallengePacket) String() string { 95 return fmt.Sprintf("Code: Challenge Challenge: %#v Name: %s", p.Challenge, p.Name) 96 } 97 func (p *ChallengePacket) OpCode() OpCode { 98 return OpCodeChallenge 99 } 100 func (p *ChallengePacket) Encode() (b []byte) { 101 len := 4 + 1 + 16 + len(p.Name) 102 b = make([]byte, len) 103 b[0] = byte(p.OpCode()) 104 b[1] = byte(p.Identifier) 105 binary.BigEndian.PutUint16(b[2:4], uint16(len)) 106 b[4] = 16 107 copy(b[5:21], p.Challenge[:]) 108 copy(b[21:], p.Name) 109 return b 110 } 111 112 type ResponsePacket struct { 113 Identifier uint8 114 PeerChallenge [16]byte //16byte 115 NTResponse [24]byte //24byte 116 Name string 117 } 118 119 func (p *ResponsePacket) String() string { 120 return fmt.Sprintf("Code: Response PeerChallenge: %#v NTResponse:%#v Name:%#v", p.PeerChallenge, p.NTResponse, p.Name) 121 } 122 func (p *ResponsePacket) OpCode() OpCode { 123 return OpCodeResponse 124 } 125 func (p *ResponsePacket) Encode() (b []byte) { 126 len := 4 + 1 + 49 + len(p.Name) 127 b = make([]byte, len) 128 b[0] = byte(p.OpCode()) 129 b[1] = byte(p.Identifier) 130 binary.BigEndian.PutUint16(b[2:4], uint16(len)) 131 b[4] = 49 132 copy(b[5:21], p.PeerChallenge[:]) 133 copy(b[29:53], p.NTResponse[:]) 134 copy(b[54:], p.Name) 135 return b 136 } 137 138 // look like "S=<auth_string> M=<message>" 139 type SuccessPacket struct { 140 Identifier uint8 141 Auth [20]byte // the binary format of auth_string 142 Message string 143 } 144 145 func (p *SuccessPacket) String() string { 146 return fmt.Sprintf("Code: Success AuthString: %#v Message: %s", p.Auth, p.Message) 147 } 148 149 func (p *SuccessPacket) OpCode() OpCode { 150 return OpCodeSuccess 151 } 152 func (p *SuccessPacket) Encode() (b []byte) { 153 len := 4 + 2 + 40 + 3 + len(p.Message) 154 b = make([]byte, len) 155 b[0] = byte(p.OpCode()) 156 b[1] = byte(p.Identifier) 157 binary.BigEndian.PutUint16(b[2:4], uint16(len)) 158 copy(b[4:6], "S=") 159 hex.Encode(b[6:46], p.Auth[:]) 160 out := bytes.ToUpper(b[6:46]) 161 copy(b[6:46], out) 162 copy(b[46:49], " M=") 163 copy(b[49:], p.Message) 164 return b 165 } 166 167 type SimplePacket struct { 168 Code OpCode 169 } 170 171 func (p *SimplePacket) OpCode() OpCode { 172 return p.Code 173 } 174 175 func (p *SimplePacket) String() string { 176 return fmt.Sprintf("Code: %s", p.OpCode()) 177 } 178 179 func (p *SimplePacket) Encode() (b []byte) { 180 b = make([]byte, 1) 181 b[0] = byte(p.OpCode()) 182 return b 183 } 184 185 type ReplySuccessPacketRequest struct { 186 AuthenticatorChallenge [16]byte 187 Response *ResponsePacket 188 Username []byte 189 Password []byte 190 Message string 191 } 192 193 func ReplySuccessPacket(req *ReplySuccessPacketRequest) (p *SuccessPacket) { 194 Auth := GenerateAuthenticatorResponse(req.Password, req.Response.NTResponse, req.Response.PeerChallenge, req.AuthenticatorChallenge, req.Username) 195 return &SuccessPacket{ 196 Identifier: req.Response.Identifier, 197 Auth: Auth, 198 Message: req.Message, 199 } 200 }