github.com/gopacket/gopacket@v1.1.0/layers/radius.go (about) 1 // Copyright 2020 The GoPacket Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style license that can be found 4 // in the LICENSE file in the root of the source tree. 5 6 package layers 7 8 import ( 9 "encoding/binary" 10 "fmt" 11 12 "github.com/gopacket/gopacket" 13 ) 14 15 const ( 16 // RFC 2865 3. Packet Format 17 // `The minimum length is 20 and maximum length is 4096.` 18 radiusMinimumRecordSizeInBytes int = 20 19 radiusMaximumRecordSizeInBytes int = 4096 20 21 // RFC 2865 5. Attributes 22 // `The Length field is one octet, and indicates the length of this Attribute including the Type, Length and Value fields.` 23 // `The Value field is zero or more octets and contains information specific to the Attribute.` 24 radiusAttributesMinimumRecordSizeInBytes int = 2 25 ) 26 27 // RADIUS represents a Remote Authentication Dial In User Service layer. 28 type RADIUS struct { 29 BaseLayer 30 31 Code RADIUSCode 32 Identifier RADIUSIdentifier 33 Length RADIUSLength 34 Authenticator RADIUSAuthenticator 35 Attributes []RADIUSAttribute 36 } 37 38 // RADIUSCode represents packet type. 39 type RADIUSCode uint8 40 41 // constants that define RADIUSCode. 42 const ( 43 RADIUSCodeAccessRequest RADIUSCode = 1 // RFC2865 3. Packet Format 44 RADIUSCodeAccessAccept RADIUSCode = 2 // RFC2865 3. Packet Format 45 RADIUSCodeAccessReject RADIUSCode = 3 // RFC2865 3. Packet Format 46 RADIUSCodeAccountingRequest RADIUSCode = 4 // RFC2865 3. Packet Format 47 RADIUSCodeAccountingResponse RADIUSCode = 5 // RFC2865 3. Packet Format 48 RADIUSCodeAccessChallenge RADIUSCode = 11 // RFC2865 3. Packet Format 49 RADIUSCodeStatusServer RADIUSCode = 12 // RFC2865 3. Packet Format (experimental) 50 RADIUSCodeStatusClient RADIUSCode = 13 // RFC2865 3. Packet Format (experimental) 51 RADIUSCodeReserved RADIUSCode = 255 // RFC2865 3. Packet Format 52 ) 53 54 // String returns a string version of a RADIUSCode. 55 func (t RADIUSCode) String() (s string) { 56 switch t { 57 case RADIUSCodeAccessRequest: 58 s = "Access-Request" 59 case RADIUSCodeAccessAccept: 60 s = "Access-Accept" 61 case RADIUSCodeAccessReject: 62 s = "Access-Reject" 63 case RADIUSCodeAccountingRequest: 64 s = "Accounting-Request" 65 case RADIUSCodeAccountingResponse: 66 s = "Accounting-Response" 67 case RADIUSCodeAccessChallenge: 68 s = "Access-Challenge" 69 case RADIUSCodeStatusServer: 70 s = "Status-Server" 71 case RADIUSCodeStatusClient: 72 s = "Status-Client" 73 case RADIUSCodeReserved: 74 s = "Reserved" 75 default: 76 s = fmt.Sprintf("Unknown(%d)", t) 77 } 78 return 79 } 80 81 // RADIUSIdentifier represents packet identifier. 82 type RADIUSIdentifier uint8 83 84 // RADIUSLength represents packet length. 85 type RADIUSLength uint16 86 87 // RADIUSAuthenticator represents authenticator. 88 type RADIUSAuthenticator [16]byte 89 90 // RADIUSAttribute represents attributes. 91 type RADIUSAttribute struct { 92 Type RADIUSAttributeType 93 Length RADIUSAttributeLength 94 Value RADIUSAttributeValue 95 } 96 97 // RADIUSAttributeType represents attribute type. 98 type RADIUSAttributeType uint8 99 100 // constants that define RADIUSAttributeType. 101 const ( 102 RADIUSAttributeTypeUserName RADIUSAttributeType = 1 // RFC2865 5.1. User-Name 103 RADIUSAttributeTypeUserPassword RADIUSAttributeType = 2 // RFC2865 5.2. User-Password 104 RADIUSAttributeTypeCHAPPassword RADIUSAttributeType = 3 // RFC2865 5.3. CHAP-Password 105 RADIUSAttributeTypeNASIPAddress RADIUSAttributeType = 4 // RFC2865 5.4. NAS-IP-Address 106 RADIUSAttributeTypeNASPort RADIUSAttributeType = 5 // RFC2865 5.5. NAS-Port 107 RADIUSAttributeTypeServiceType RADIUSAttributeType = 6 // RFC2865 5.6. Service-Type 108 RADIUSAttributeTypeFramedProtocol RADIUSAttributeType = 7 // RFC2865 5.7. Framed-Protocol 109 RADIUSAttributeTypeFramedIPAddress RADIUSAttributeType = 8 // RFC2865 5.8. Framed-IP-Address 110 RADIUSAttributeTypeFramedIPNetmask RADIUSAttributeType = 9 // RFC2865 5.9. Framed-IP-Netmask 111 RADIUSAttributeTypeFramedRouting RADIUSAttributeType = 10 // RFC2865 5.10. Framed-Routing 112 RADIUSAttributeTypeFilterId RADIUSAttributeType = 11 // RFC2865 5.11. Filter-Id 113 RADIUSAttributeTypeFramedMTU RADIUSAttributeType = 12 // RFC2865 5.12. Framed-MTU 114 RADIUSAttributeTypeFramedCompression RADIUSAttributeType = 13 // RFC2865 5.13. Framed-Compression 115 RADIUSAttributeTypeLoginIPHost RADIUSAttributeType = 14 // RFC2865 5.14. Login-IP-Host 116 RADIUSAttributeTypeLoginService RADIUSAttributeType = 15 // RFC2865 5.15. Login-Service 117 RADIUSAttributeTypeLoginTCPPort RADIUSAttributeType = 16 // RFC2865 5.16. Login-TCP-Port 118 RADIUSAttributeTypeReplyMessage RADIUSAttributeType = 18 // RFC2865 5.18. Reply-Message 119 RADIUSAttributeTypeCallbackNumber RADIUSAttributeType = 19 // RFC2865 5.19. Callback-Number 120 RADIUSAttributeTypeCallbackId RADIUSAttributeType = 20 // RFC2865 5.20. Callback-Id 121 RADIUSAttributeTypeFramedRoute RADIUSAttributeType = 22 // RFC2865 5.22. Framed-Route 122 RADIUSAttributeTypeFramedIPXNetwork RADIUSAttributeType = 23 // RFC2865 5.23. Framed-IPX-Network 123 RADIUSAttributeTypeState RADIUSAttributeType = 24 // RFC2865 5.24. State 124 RADIUSAttributeTypeClass RADIUSAttributeType = 25 // RFC2865 5.25. Class 125 RADIUSAttributeTypeVendorSpecific RADIUSAttributeType = 26 // RFC2865 5.26. Vendor-Specific 126 RADIUSAttributeTypeSessionTimeout RADIUSAttributeType = 27 // RFC2865 5.27. Session-Timeout 127 RADIUSAttributeTypeIdleTimeout RADIUSAttributeType = 28 // RFC2865 5.28. Idle-Timeout 128 RADIUSAttributeTypeTerminationAction RADIUSAttributeType = 29 // RFC2865 5.29. Termination-Action 129 RADIUSAttributeTypeCalledStationId RADIUSAttributeType = 30 // RFC2865 5.30. Called-Station-Id 130 RADIUSAttributeTypeCallingStationId RADIUSAttributeType = 31 // RFC2865 5.31. Calling-Station-Id 131 RADIUSAttributeTypeNASIdentifier RADIUSAttributeType = 32 // RFC2865 5.32. NAS-Identifier 132 RADIUSAttributeTypeProxyState RADIUSAttributeType = 33 // RFC2865 5.33. Proxy-State 133 RADIUSAttributeTypeLoginLATService RADIUSAttributeType = 34 // RFC2865 5.34. Login-LAT-Service 134 RADIUSAttributeTypeLoginLATNode RADIUSAttributeType = 35 // RFC2865 5.35. Login-LAT-Node 135 RADIUSAttributeTypeLoginLATGroup RADIUSAttributeType = 36 // RFC2865 5.36. Login-LAT-Group 136 RADIUSAttributeTypeFramedAppleTalkLink RADIUSAttributeType = 37 // RFC2865 5.37. Framed-AppleTalk-Link 137 RADIUSAttributeTypeFramedAppleTalkNetwork RADIUSAttributeType = 38 // RFC2865 5.38. Framed-AppleTalk-Network 138 RADIUSAttributeTypeFramedAppleTalkZone RADIUSAttributeType = 39 // RFC2865 5.39. Framed-AppleTalk-Zone 139 RADIUSAttributeTypeAcctStatusType RADIUSAttributeType = 40 // RFC2866 5.1. Acct-Status-Type 140 RADIUSAttributeTypeAcctDelayTime RADIUSAttributeType = 41 // RFC2866 5.2. Acct-Delay-Time 141 RADIUSAttributeTypeAcctInputOctets RADIUSAttributeType = 42 // RFC2866 5.3. Acct-Input-Octets 142 RADIUSAttributeTypeAcctOutputOctets RADIUSAttributeType = 43 // RFC2866 5.4. Acct-Output-Octets 143 RADIUSAttributeTypeAcctSessionId RADIUSAttributeType = 44 // RFC2866 5.5. Acct-Session-Id 144 RADIUSAttributeTypeAcctAuthentic RADIUSAttributeType = 45 // RFC2866 5.6. Acct-Authentic 145 RADIUSAttributeTypeAcctSessionTime RADIUSAttributeType = 46 // RFC2866 5.7. Acct-Session-Time 146 RADIUSAttributeTypeAcctInputPackets RADIUSAttributeType = 47 // RFC2866 5.8. Acct-Input-Packets 147 RADIUSAttributeTypeAcctOutputPackets RADIUSAttributeType = 48 // RFC2866 5.9. Acct-Output-Packets 148 RADIUSAttributeTypeAcctTerminateCause RADIUSAttributeType = 49 // RFC2866 5.10. Acct-Terminate-Cause 149 RADIUSAttributeTypeAcctMultiSessionId RADIUSAttributeType = 50 // RFC2866 5.11. Acct-Multi-Session-Id 150 RADIUSAttributeTypeAcctLinkCount RADIUSAttributeType = 51 // RFC2866 5.12. Acct-Link-Count 151 RADIUSAttributeTypeAcctInputGigawords RADIUSAttributeType = 52 // RFC2869 5.1. Acct-Input-Gigawords 152 RADIUSAttributeTypeAcctOutputGigawords RADIUSAttributeType = 53 // RFC2869 5.2. Acct-Output-Gigawords 153 RADIUSAttributeTypeEventTimestamp RADIUSAttributeType = 55 // RFC2869 5.3. Event-Timestamp 154 RADIUSAttributeTypeCHAPChallenge RADIUSAttributeType = 60 // RFC2865 5.40. CHAP-Challenge 155 RADIUSAttributeTypeNASPortType RADIUSAttributeType = 61 // RFC2865 5.41. NAS-Port-Type 156 RADIUSAttributeTypePortLimit RADIUSAttributeType = 62 // RFC2865 5.42. Port-Limit 157 RADIUSAttributeTypeLoginLATPort RADIUSAttributeType = 63 // RFC2865 5.43. Login-LAT-Port 158 RADIUSAttributeTypeTunnelType RADIUSAttributeType = 64 // RFC2868 3.1. Tunnel-Type 159 RADIUSAttributeTypeTunnelMediumType RADIUSAttributeType = 65 // RFC2868 3.2. Tunnel-Medium-Type 160 RADIUSAttributeTypeTunnelClientEndpoint RADIUSAttributeType = 66 // RFC2868 3.3. Tunnel-Client-Endpoint 161 RADIUSAttributeTypeTunnelServerEndpoint RADIUSAttributeType = 67 // RFC2868 3.4. Tunnel-Server-Endpoint 162 RADIUSAttributeTypeAcctTunnelConnection RADIUSAttributeType = 68 // RFC2867 4.1. Acct-Tunnel-Connection 163 RADIUSAttributeTypeTunnelPassword RADIUSAttributeType = 69 // RFC2868 3.5. Tunnel-Password 164 RADIUSAttributeTypeARAPPassword RADIUSAttributeType = 70 // RFC2869 5.4. ARAP-Password 165 RADIUSAttributeTypeARAPFeatures RADIUSAttributeType = 71 // RFC2869 5.5. ARAP-Features 166 RADIUSAttributeTypeARAPZoneAccess RADIUSAttributeType = 72 // RFC2869 5.6. ARAP-Zone-Access 167 RADIUSAttributeTypeARAPSecurity RADIUSAttributeType = 73 // RFC2869 5.7. ARAP-Security 168 RADIUSAttributeTypeARAPSecurityData RADIUSAttributeType = 74 // RFC2869 5.8. ARAP-Security-Data 169 RADIUSAttributeTypePasswordRetry RADIUSAttributeType = 75 // RFC2869 5.9. Password-Retry 170 RADIUSAttributeTypePrompt RADIUSAttributeType = 76 // RFC2869 5.10. Prompt 171 RADIUSAttributeTypeConnectInfo RADIUSAttributeType = 77 // RFC2869 5.11. Connect-Info 172 RADIUSAttributeTypeConfigurationToken RADIUSAttributeType = 78 // RFC2869 5.12. Configuration-Token 173 RADIUSAttributeTypeEAPMessage RADIUSAttributeType = 79 // RFC2869 5.13. EAP-Message 174 RADIUSAttributeTypeMessageAuthenticator RADIUSAttributeType = 80 // RFC2869 5.14. Message-Authenticator 175 RADIUSAttributeTypeTunnelPrivateGroupID RADIUSAttributeType = 81 // RFC2868 3.6. Tunnel-Private-Group-ID 176 RADIUSAttributeTypeTunnelAssignmentID RADIUSAttributeType = 82 // RFC2868 3.7. Tunnel-Assignment-ID 177 RADIUSAttributeTypeTunnelPreference RADIUSAttributeType = 83 // RFC2868 3.8. Tunnel-Preference 178 RADIUSAttributeTypeARAPChallengeResponse RADIUSAttributeType = 84 // RFC2869 5.15. ARAP-Challenge-Response 179 RADIUSAttributeTypeAcctInterimInterval RADIUSAttributeType = 85 // RFC2869 5.16. Acct-Interim-Interval 180 RADIUSAttributeTypeAcctTunnelPacketsLost RADIUSAttributeType = 86 // RFC2867 4.2. Acct-Tunnel-Packets-Lost 181 RADIUSAttributeTypeNASPortId RADIUSAttributeType = 87 // RFC2869 5.17. NAS-Port-Id 182 RADIUSAttributeTypeFramedPool RADIUSAttributeType = 88 // RFC2869 5.18. Framed-Pool 183 RADIUSAttributeTypeTunnelClientAuthID RADIUSAttributeType = 90 // RFC2868 3.9. Tunnel-Client-Auth-ID 184 RADIUSAttributeTypeTunnelServerAuthID RADIUSAttributeType = 91 // RFC2868 3.10. Tunnel-Server-Auth-ID 185 ) 186 187 // RADIUSAttributeType represents attribute length. 188 type RADIUSAttributeLength uint8 189 190 // RADIUSAttributeType represents attribute value. 191 type RADIUSAttributeValue []byte 192 193 // String returns a string version of a RADIUSAttributeType. 194 func (t RADIUSAttributeType) String() (s string) { 195 switch t { 196 case RADIUSAttributeTypeUserName: 197 s = "User-Name" 198 case RADIUSAttributeTypeUserPassword: 199 s = "User-Password" 200 case RADIUSAttributeTypeCHAPPassword: 201 s = "CHAP-Password" 202 case RADIUSAttributeTypeNASIPAddress: 203 s = "NAS-IP-Address" 204 case RADIUSAttributeTypeNASPort: 205 s = "NAS-Port" 206 case RADIUSAttributeTypeServiceType: 207 s = "Service-Type" 208 case RADIUSAttributeTypeFramedProtocol: 209 s = "Framed-Protocol" 210 case RADIUSAttributeTypeFramedIPAddress: 211 s = "Framed-IP-Address" 212 case RADIUSAttributeTypeFramedIPNetmask: 213 s = "Framed-IP-Netmask" 214 case RADIUSAttributeTypeFramedRouting: 215 s = "Framed-Routing" 216 case RADIUSAttributeTypeFilterId: 217 s = "Filter-Id" 218 case RADIUSAttributeTypeFramedMTU: 219 s = "Framed-MTU" 220 case RADIUSAttributeTypeFramedCompression: 221 s = "Framed-Compression" 222 case RADIUSAttributeTypeLoginIPHost: 223 s = "Login-IP-Host" 224 case RADIUSAttributeTypeLoginService: 225 s = "Login-Service" 226 case RADIUSAttributeTypeLoginTCPPort: 227 s = "Login-TCP-Port" 228 case RADIUSAttributeTypeReplyMessage: 229 s = "Reply-Message" 230 case RADIUSAttributeTypeCallbackNumber: 231 s = "Callback-Number" 232 case RADIUSAttributeTypeCallbackId: 233 s = "Callback-Id" 234 case RADIUSAttributeTypeFramedRoute: 235 s = "Framed-Route" 236 case RADIUSAttributeTypeFramedIPXNetwork: 237 s = "Framed-IPX-Network" 238 case RADIUSAttributeTypeState: 239 s = "State" 240 case RADIUSAttributeTypeClass: 241 s = "Class" 242 case RADIUSAttributeTypeVendorSpecific: 243 s = "Vendor-Specific" 244 case RADIUSAttributeTypeSessionTimeout: 245 s = "Session-Timeout" 246 case RADIUSAttributeTypeIdleTimeout: 247 s = "Idle-Timeout" 248 case RADIUSAttributeTypeTerminationAction: 249 s = "Termination-Action" 250 case RADIUSAttributeTypeCalledStationId: 251 s = "Called-Station-Id" 252 case RADIUSAttributeTypeCallingStationId: 253 s = "Calling-Station-Id" 254 case RADIUSAttributeTypeNASIdentifier: 255 s = "NAS-Identifier" 256 case RADIUSAttributeTypeProxyState: 257 s = "Proxy-State" 258 case RADIUSAttributeTypeLoginLATService: 259 s = "Login-LAT-Service" 260 case RADIUSAttributeTypeLoginLATNode: 261 s = "Login-LAT-Node" 262 case RADIUSAttributeTypeLoginLATGroup: 263 s = "Login-LAT-Group" 264 case RADIUSAttributeTypeFramedAppleTalkLink: 265 s = "Framed-AppleTalk-Link" 266 case RADIUSAttributeTypeFramedAppleTalkNetwork: 267 s = "Framed-AppleTalk-Network" 268 case RADIUSAttributeTypeFramedAppleTalkZone: 269 s = "Framed-AppleTalk-Zone" 270 case RADIUSAttributeTypeAcctStatusType: 271 s = "Acct-Status-Type" 272 case RADIUSAttributeTypeAcctDelayTime: 273 s = "Acct-Delay-Time" 274 case RADIUSAttributeTypeAcctInputOctets: 275 s = "Acct-Input-Octets" 276 case RADIUSAttributeTypeAcctOutputOctets: 277 s = "Acct-Output-Octets" 278 case RADIUSAttributeTypeAcctSessionId: 279 s = "Acct-Session-Id" 280 case RADIUSAttributeTypeAcctAuthentic: 281 s = "Acct-Authentic" 282 case RADIUSAttributeTypeAcctSessionTime: 283 s = "Acct-Session-Time" 284 case RADIUSAttributeTypeAcctInputPackets: 285 s = "Acct-Input-Packets" 286 case RADIUSAttributeTypeAcctOutputPackets: 287 s = "Acct-Output-Packets" 288 case RADIUSAttributeTypeAcctTerminateCause: 289 s = "Acct-Terminate-Cause" 290 case RADIUSAttributeTypeAcctMultiSessionId: 291 s = "Acct-Multi-Session-Id" 292 case RADIUSAttributeTypeAcctLinkCount: 293 s = "Acct-Link-Count" 294 case RADIUSAttributeTypeAcctInputGigawords: 295 s = "Acct-Input-Gigawords" 296 case RADIUSAttributeTypeAcctOutputGigawords: 297 s = "Acct-Output-Gigawords" 298 case RADIUSAttributeTypeEventTimestamp: 299 s = "Event-Timestamp" 300 case RADIUSAttributeTypeCHAPChallenge: 301 s = "CHAP-Challenge" 302 case RADIUSAttributeTypeNASPortType: 303 s = "NAS-Port-Type" 304 case RADIUSAttributeTypePortLimit: 305 s = "Port-Limit" 306 case RADIUSAttributeTypeLoginLATPort: 307 s = "Login-LAT-Port" 308 case RADIUSAttributeTypeTunnelType: 309 s = "Tunnel-Type" 310 case RADIUSAttributeTypeTunnelMediumType: 311 s = "Tunnel-Medium-Type" 312 case RADIUSAttributeTypeTunnelClientEndpoint: 313 s = "Tunnel-Client-Endpoint" 314 case RADIUSAttributeTypeTunnelServerEndpoint: 315 s = "Tunnel-Server-Endpoint" 316 case RADIUSAttributeTypeAcctTunnelConnection: 317 s = "Acct-Tunnel-Connection" 318 case RADIUSAttributeTypeTunnelPassword: 319 s = "Tunnel-Password" 320 case RADIUSAttributeTypeARAPPassword: 321 s = "ARAP-Password" 322 case RADIUSAttributeTypeARAPFeatures: 323 s = "ARAP-Features" 324 case RADIUSAttributeTypeARAPZoneAccess: 325 s = "ARAP-Zone-Access" 326 case RADIUSAttributeTypeARAPSecurity: 327 s = "ARAP-Security" 328 case RADIUSAttributeTypeARAPSecurityData: 329 s = "ARAP-Security-Data" 330 case RADIUSAttributeTypePasswordRetry: 331 s = "Password-Retry" 332 case RADIUSAttributeTypePrompt: 333 s = "Prompt" 334 case RADIUSAttributeTypeConnectInfo: 335 s = "Connect-Info" 336 case RADIUSAttributeTypeConfigurationToken: 337 s = "Configuration-Token" 338 case RADIUSAttributeTypeEAPMessage: 339 s = "EAP-Message" 340 case RADIUSAttributeTypeMessageAuthenticator: 341 s = "Message-Authenticator" 342 case RADIUSAttributeTypeTunnelPrivateGroupID: 343 s = "Tunnel-Private-Group-ID" 344 case RADIUSAttributeTypeTunnelAssignmentID: 345 s = "Tunnel-Assignment-ID" 346 case RADIUSAttributeTypeTunnelPreference: 347 s = "Tunnel-Preference" 348 case RADIUSAttributeTypeARAPChallengeResponse: 349 s = "ARAP-Challenge-Response" 350 case RADIUSAttributeTypeAcctInterimInterval: 351 s = "Acct-Interim-Interval" 352 case RADIUSAttributeTypeAcctTunnelPacketsLost: 353 s = "Acct-Tunnel-Packets-Lost" 354 case RADIUSAttributeTypeNASPortId: 355 s = "NAS-Port-Id" 356 case RADIUSAttributeTypeFramedPool: 357 s = "Framed-Pool" 358 case RADIUSAttributeTypeTunnelClientAuthID: 359 s = "Tunnel-Client-Auth-ID" 360 case RADIUSAttributeTypeTunnelServerAuthID: 361 s = "Tunnel-Server-Auth-ID" 362 default: 363 s = fmt.Sprintf("Unknown(%d)", t) 364 } 365 return 366 } 367 368 // Len returns the length of a RADIUS packet. 369 func (radius *RADIUS) Len() (int, error) { 370 n := radiusMinimumRecordSizeInBytes 371 for _, v := range radius.Attributes { 372 alen, err := attributeValueLength(v.Value) 373 if err != nil { 374 return 0, err 375 } 376 n += int(alen) + 2 // Added Type and Length 377 } 378 return n, nil 379 } 380 381 // LayerType returns LayerTypeRADIUS. 382 func (radius *RADIUS) LayerType() gopacket.LayerType { 383 return LayerTypeRADIUS 384 } 385 386 // DecodeFromBytes decodes the given bytes into this layer. 387 func (radius *RADIUS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 388 if len(data) > radiusMaximumRecordSizeInBytes { 389 df.SetTruncated() 390 return fmt.Errorf("RADIUS length %d too big", len(data)) 391 } 392 393 if len(data) < radiusMinimumRecordSizeInBytes { 394 df.SetTruncated() 395 return fmt.Errorf("RADIUS length %d too short", len(data)) 396 } 397 398 radius.BaseLayer = BaseLayer{Contents: data} 399 400 radius.Code = RADIUSCode(data[0]) 401 radius.Identifier = RADIUSIdentifier(data[1]) 402 radius.Length = RADIUSLength(binary.BigEndian.Uint16(data[2:4])) 403 404 if int(radius.Length) > radiusMaximumRecordSizeInBytes { 405 df.SetTruncated() 406 return fmt.Errorf("RADIUS length %d too big", radius.Length) 407 } 408 409 if int(radius.Length) < radiusMinimumRecordSizeInBytes { 410 df.SetTruncated() 411 return fmt.Errorf("RADIUS length %d too short", radius.Length) 412 } 413 414 // RFC 2865 3. Packet Format 415 // `If the packet is shorter than the Length field indicates, it MUST be silently discarded.` 416 if int(radius.Length) > len(data) { 417 df.SetTruncated() 418 return fmt.Errorf("RADIUS length %d too big", radius.Length) 419 } 420 421 // RFC 2865 3. Packet Format 422 // `Octets outside the range of the Length field MUST be treated as padding and ignored on reception.` 423 if int(radius.Length) < len(data) { 424 df.SetTruncated() 425 data = data[:radius.Length] 426 } 427 428 copy(radius.Authenticator[:], data[4:20]) 429 430 if len(data) == radiusMinimumRecordSizeInBytes { 431 return nil 432 } 433 434 pos := radiusMinimumRecordSizeInBytes 435 for { 436 if len(data) == pos { 437 break 438 } 439 440 if len(data[pos:]) < radiusAttributesMinimumRecordSizeInBytes { 441 df.SetTruncated() 442 return fmt.Errorf("RADIUS attributes length %d too short", len(data[pos:])) 443 } 444 445 attr := RADIUSAttribute{} 446 attr.Type = RADIUSAttributeType(data[pos]) 447 attr.Length = RADIUSAttributeLength(data[pos+1]) 448 449 if int(attr.Length) > len(data[pos:]) { 450 df.SetTruncated() 451 return fmt.Errorf("RADIUS attributes length %d too big", attr.Length) 452 } 453 454 if int(attr.Length) < radiusAttributesMinimumRecordSizeInBytes { 455 df.SetTruncated() 456 return fmt.Errorf("RADIUS attributes length %d too short", attr.Length) 457 } 458 459 if int(attr.Length) > radiusAttributesMinimumRecordSizeInBytes { 460 attr.Value = make([]byte, attr.Length-2) 461 copy(attr.Value[:], data[pos+2:pos+int(attr.Length)]) 462 radius.Attributes = append(radius.Attributes, attr) 463 } 464 465 pos += int(attr.Length) 466 } 467 468 for _, v := range radius.Attributes { 469 if v.Type == RADIUSAttributeTypeEAPMessage { 470 radius.BaseLayer.Payload = append(radius.BaseLayer.Payload, v.Value...) 471 } 472 } 473 474 return nil 475 } 476 477 // SerializeTo writes the serialized form of this layer into the 478 // SerializationBuffer, implementing gopacket.SerializableLayer. 479 // See the docs for gopacket.SerializableLayer for more info. 480 func (radius *RADIUS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 481 plen, err := radius.Len() 482 if err != nil { 483 return err 484 } 485 486 if opts.FixLengths { 487 radius.Length = RADIUSLength(plen) 488 } 489 490 data, err := b.PrependBytes(plen) 491 if err != nil { 492 return err 493 } 494 495 data[0] = byte(radius.Code) 496 data[1] = byte(radius.Identifier) 497 binary.BigEndian.PutUint16(data[2:], uint16(radius.Length)) 498 copy(data[4:20], radius.Authenticator[:]) 499 500 pos := radiusMinimumRecordSizeInBytes 501 for _, v := range radius.Attributes { 502 if opts.FixLengths { 503 v.Length, err = attributeValueLength(v.Value) 504 if err != nil { 505 return err 506 } 507 } 508 509 data[pos] = byte(v.Type) 510 data[pos+1] = byte(v.Length) 511 copy(data[pos+2:], v.Value[:]) 512 513 pos += len(v.Value) + 2 // Added Type and Length 514 } 515 516 return nil 517 } 518 519 // CanDecode returns the set of layer types that this DecodingLayer can decode. 520 func (radius *RADIUS) CanDecode() gopacket.LayerClass { 521 return LayerTypeRADIUS 522 } 523 524 // NextLayerType returns the layer type contained by this DecodingLayer. 525 func (radius *RADIUS) NextLayerType() gopacket.LayerType { 526 if len(radius.BaseLayer.Payload) > 0 { 527 return LayerTypeEAP 528 } else { 529 return gopacket.LayerTypeZero 530 } 531 } 532 533 // Payload returns the EAP Type-Data for EAP-Message attributes. 534 func (radius *RADIUS) Payload() []byte { 535 return radius.BaseLayer.Payload 536 } 537 538 func decodeRADIUS(data []byte, p gopacket.PacketBuilder) error { 539 radius := &RADIUS{} 540 err := radius.DecodeFromBytes(data, p) 541 if err != nil { 542 return err 543 } 544 p.AddLayer(radius) 545 p.SetApplicationLayer(radius) 546 next := radius.NextLayerType() 547 if next == gopacket.LayerTypeZero { 548 return nil 549 } 550 return p.NextDecoder(next) 551 } 552 553 func attributeValueLength(v []byte) (RADIUSAttributeLength, error) { 554 n := len(v) 555 if n > 255 { 556 return 0, fmt.Errorf("RADIUS attribute value length %d too long", n) 557 } else { 558 return RADIUSAttributeLength(n), nil 559 } 560 }