github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgRadius/eap/eap.go (about) 1 package eap 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "strconv" 7 8 "github.com/bronze1man/kmg/third/kmgRadius/MSCHAPV2" 9 ) 10 11 type Code uint8 12 13 const ( 14 CodeRequest Code = 1 15 CodeResponse Code = 2 16 CodeSuccess Code = 3 17 CodeFailure Code = 4 18 ) 19 20 func (c Code) String() string { 21 switch c { 22 case CodeRequest: 23 return "Request" 24 case CodeResponse: 25 return "Response" 26 case CodeSuccess: 27 return "Success" 28 case CodeFailure: 29 return "Failure" 30 default: 31 return "unknow Code " + strconv.Itoa(int(c)) 32 } 33 } 34 35 type Type uint8 36 37 const ( 38 TypeIdentity Type = 1 39 TypeNotification Type = 2 40 TypeLegacyNak Type = 3 //Response only 41 TypeMd5Challenge Type = 4 42 TypeOneTimePassword Type = 5 //otp 43 TypeGenericTokenCard Type = 6 //gtc 44 TypeMSCHAPV2 Type = 26 45 TypeExpandedTypes Type = 254 46 TypeExperimentalUse Type = 255 47 ) 48 49 func (c Type) String() string { 50 switch c { 51 case TypeIdentity: 52 return "Identity" 53 case TypeNotification: 54 return "Notification" 55 case TypeLegacyNak: 56 return "LegacyNak" 57 case TypeMd5Challenge: 58 return "Md5Challenge" 59 case TypeOneTimePassword: 60 return "OneTimePassword" 61 case TypeGenericTokenCard: 62 return "GenericTokenCard" 63 case TypeMSCHAPV2: 64 return "MSCHAPV2" 65 case TypeExpandedTypes: 66 return "ExpandedTypes" 67 case TypeExperimentalUse: 68 return "ExperimentalUse" 69 default: 70 return "unknow Type " + strconv.Itoa(int(c)) 71 } 72 } 73 74 type Packet interface { 75 Header() *PacketHeader 76 String() string 77 Encode() []byte 78 } 79 80 func Decode(b []byte) (p Packet, err error) { 81 if len(b) < 4 { 82 return nil, fmt.Errorf("[eap.Decode] protocol error input too small 1 len(b)[%d] < 4", len(b)) 83 } 84 code := Code(b[0]) 85 switch code { 86 case CodeRequest, CodeResponse: 87 if len(b) < 5 { 88 return nil, fmt.Errorf("[eap.Decode] protocol error input too small 1 len(b)[%d] < 5", len(b)) 89 } 90 length := binary.BigEndian.Uint16(b[2:4]) 91 if len(b) != int(length) { 92 return nil, fmt.Errorf("[eap.Decode] protocol error input too small 2 len(b)[%d] != int(length)[%d]", len(b), length) 93 } 94 h := PacketHeader{ 95 Code: Code(b[0]), 96 Identifier: uint8(b[1]), 97 Type: Type(b[4]), 98 } 99 data := b[5:length] 100 switch h.Type { 101 case TypeIdentity: 102 return &IdentityPacket{ 103 PacketHeader: h, 104 Identity: string(data), 105 }, nil 106 case TypeMSCHAPV2: 107 MSCHAPV2, err := MSCHAPV2.Decode(data) 108 if err != nil { 109 return nil, err 110 } 111 return &MSCHAPV2Packet{ 112 PacketHeader: h, 113 MSCHAPV2: MSCHAPV2, 114 }, nil 115 case TypeLegacyNak: 116 if len(data) == 0 { 117 return nil, fmt.Errorf("[eap.Decode] Type: LegacyNak len==0") 118 } 119 return &LegacyNakPacket{ 120 PacketHeader: h, 121 DesiredAuthType: Type(data[0]), 122 }, nil 123 default: 124 return nil, fmt.Errorf("[eap.Decode] Type:%s not implement", h.Type) 125 } 126 case CodeSuccess, CodeFailure: 127 return &SimplePacket{ 128 PacketHeader{ 129 Code: Code(b[0]), 130 Identifier: uint8(b[1]), 131 }, 132 }, nil 133 default: 134 return nil, fmt.Errorf("unknow Code " + strconv.Itoa(int(code))) 135 } 136 } 137 138 type PacketHeader struct { 139 Code Code 140 Identifier uint8 141 Type Type //success and failure do not have any type 142 } 143 144 func (h *PacketHeader) Header() *PacketHeader { 145 return h 146 } 147 148 func (h *PacketHeader) String() string { 149 switch h.Code { 150 case CodeSuccess, CodeFailure: 151 return fmt.Sprintf("Code: %s Id:%d", h.Code, h.Identifier) 152 default: 153 return fmt.Sprintf("Code: %s Id:%d Type:%s", h.Code, h.Identifier, h.Type) 154 } 155 } 156 157 func (h *PacketHeader) encode(data []byte) (b []byte) { 158 b = make([]byte, len(data)+5) 159 b[0] = byte(h.Code) 160 b[1] = byte(h.Identifier) 161 binary.BigEndian.PutUint16(b[2:4], uint16(len(data)+5)) 162 b[4] = byte(h.Type) 163 copy(b[5:], data) 164 return b 165 } 166 167 type IdentityPacket struct { 168 PacketHeader 169 Identity string 170 } 171 172 func (p *IdentityPacket) String() string { 173 return fmt.Sprintf("%s %s", p.PacketHeader.String(), p.Identity) 174 } 175 176 func (p *IdentityPacket) Encode() []byte { 177 return p.PacketHeader.encode([]byte(p.Identity)) 178 } 179 180 type LegacyNakPacket struct { 181 PacketHeader 182 DesiredAuthType Type 183 } 184 185 func (p *LegacyNakPacket) String() string { 186 return fmt.Sprintf("%s DesiredAuthType:%s", p.PacketHeader.String(), p.DesiredAuthType) 187 } 188 189 func (p *LegacyNakPacket) Encode() []byte { 190 return p.PacketHeader.encode([]byte{byte(p.DesiredAuthType)}) 191 } 192 193 type MSCHAPV2Packet struct { 194 PacketHeader 195 MSCHAPV2 MSCHAPV2.Packet 196 } 197 198 func (p *MSCHAPV2Packet) String() string { 199 return fmt.Sprintf("%s %s", p.PacketHeader.String(), p.MSCHAPV2.String()) 200 } 201 202 func (p *MSCHAPV2Packet) Encode() []byte { 203 return p.PacketHeader.encode([]byte(p.MSCHAPV2.Encode())) 204 } 205 206 // only put code identifier 207 type SimplePacket struct { 208 PacketHeader 209 } 210 211 func (p *SimplePacket) String() string { 212 return p.PacketHeader.String() 213 } 214 215 func (p *SimplePacket) Encode() (b []byte) { 216 h := p.PacketHeader 217 b = make([]byte, 4) 218 b[0] = byte(h.Code) 219 b[1] = byte(h.Identifier) 220 binary.BigEndian.PutUint16(b[2:4], uint16(4)) 221 return b 222 }