561 lines
22 KiB
Go
561 lines
22 KiB
Go
// Copyright 2020 The GoPacket Authors. All rights reserved.
|
|
//
|
|
// Use of this source code is governed by a BSD-style license that can be found
|
|
// in the LICENSE file in the root of the source tree.
|
|
|
|
package layers
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
|
|
"github.com/google/gopacket"
|
|
)
|
|
|
|
const (
|
|
// RFC 2865 3. Packet Format
|
|
// `The minimum length is 20 and maximum length is 4096.`
|
|
radiusMinimumRecordSizeInBytes int = 20
|
|
radiusMaximumRecordSizeInBytes int = 4096
|
|
|
|
// RFC 2865 5. Attributes
|
|
// `The Length field is one octet, and indicates the length of this Attribute including the Type, Length and Value fields.`
|
|
// `The Value field is zero or more octets and contains information specific to the Attribute.`
|
|
radiusAttributesMinimumRecordSizeInBytes int = 2
|
|
)
|
|
|
|
// RADIUS represents a Remote Authentication Dial In User Service layer.
|
|
type RADIUS struct {
|
|
BaseLayer
|
|
|
|
Code RADIUSCode
|
|
Identifier RADIUSIdentifier
|
|
Length RADIUSLength
|
|
Authenticator RADIUSAuthenticator
|
|
Attributes []RADIUSAttribute
|
|
}
|
|
|
|
// RADIUSCode represents packet type.
|
|
type RADIUSCode uint8
|
|
|
|
// constants that define RADIUSCode.
|
|
const (
|
|
RADIUSCodeAccessRequest RADIUSCode = 1 // RFC2865 3. Packet Format
|
|
RADIUSCodeAccessAccept RADIUSCode = 2 // RFC2865 3. Packet Format
|
|
RADIUSCodeAccessReject RADIUSCode = 3 // RFC2865 3. Packet Format
|
|
RADIUSCodeAccountingRequest RADIUSCode = 4 // RFC2865 3. Packet Format
|
|
RADIUSCodeAccountingResponse RADIUSCode = 5 // RFC2865 3. Packet Format
|
|
RADIUSCodeAccessChallenge RADIUSCode = 11 // RFC2865 3. Packet Format
|
|
RADIUSCodeStatusServer RADIUSCode = 12 // RFC2865 3. Packet Format (experimental)
|
|
RADIUSCodeStatusClient RADIUSCode = 13 // RFC2865 3. Packet Format (experimental)
|
|
RADIUSCodeReserved RADIUSCode = 255 // RFC2865 3. Packet Format
|
|
)
|
|
|
|
// String returns a string version of a RADIUSCode.
|
|
func (t RADIUSCode) String() (s string) {
|
|
switch t {
|
|
case RADIUSCodeAccessRequest:
|
|
s = "Access-Request"
|
|
case RADIUSCodeAccessAccept:
|
|
s = "Access-Accept"
|
|
case RADIUSCodeAccessReject:
|
|
s = "Access-Reject"
|
|
case RADIUSCodeAccountingRequest:
|
|
s = "Accounting-Request"
|
|
case RADIUSCodeAccountingResponse:
|
|
s = "Accounting-Response"
|
|
case RADIUSCodeAccessChallenge:
|
|
s = "Access-Challenge"
|
|
case RADIUSCodeStatusServer:
|
|
s = "Status-Server"
|
|
case RADIUSCodeStatusClient:
|
|
s = "Status-Client"
|
|
case RADIUSCodeReserved:
|
|
s = "Reserved"
|
|
default:
|
|
s = fmt.Sprintf("Unknown(%d)", t)
|
|
}
|
|
return
|
|
}
|
|
|
|
// RADIUSIdentifier represents packet identifier.
|
|
type RADIUSIdentifier uint8
|
|
|
|
// RADIUSLength represents packet length.
|
|
type RADIUSLength uint16
|
|
|
|
// RADIUSAuthenticator represents authenticator.
|
|
type RADIUSAuthenticator [16]byte
|
|
|
|
// RADIUSAttribute represents attributes.
|
|
type RADIUSAttribute struct {
|
|
Type RADIUSAttributeType
|
|
Length RADIUSAttributeLength
|
|
Value RADIUSAttributeValue
|
|
}
|
|
|
|
// RADIUSAttributeType represents attribute type.
|
|
type RADIUSAttributeType uint8
|
|
|
|
// constants that define RADIUSAttributeType.
|
|
const (
|
|
RADIUSAttributeTypeUserName RADIUSAttributeType = 1 // RFC2865 5.1. User-Name
|
|
RADIUSAttributeTypeUserPassword RADIUSAttributeType = 2 // RFC2865 5.2. User-Password
|
|
RADIUSAttributeTypeCHAPPassword RADIUSAttributeType = 3 // RFC2865 5.3. CHAP-Password
|
|
RADIUSAttributeTypeNASIPAddress RADIUSAttributeType = 4 // RFC2865 5.4. NAS-IP-Address
|
|
RADIUSAttributeTypeNASPort RADIUSAttributeType = 5 // RFC2865 5.5. NAS-Port
|
|
RADIUSAttributeTypeServiceType RADIUSAttributeType = 6 // RFC2865 5.6. Service-Type
|
|
RADIUSAttributeTypeFramedProtocol RADIUSAttributeType = 7 // RFC2865 5.7. Framed-Protocol
|
|
RADIUSAttributeTypeFramedIPAddress RADIUSAttributeType = 8 // RFC2865 5.8. Framed-IP-Address
|
|
RADIUSAttributeTypeFramedIPNetmask RADIUSAttributeType = 9 // RFC2865 5.9. Framed-IP-Netmask
|
|
RADIUSAttributeTypeFramedRouting RADIUSAttributeType = 10 // RFC2865 5.10. Framed-Routing
|
|
RADIUSAttributeTypeFilterId RADIUSAttributeType = 11 // RFC2865 5.11. Filter-Id
|
|
RADIUSAttributeTypeFramedMTU RADIUSAttributeType = 12 // RFC2865 5.12. Framed-MTU
|
|
RADIUSAttributeTypeFramedCompression RADIUSAttributeType = 13 // RFC2865 5.13. Framed-Compression
|
|
RADIUSAttributeTypeLoginIPHost RADIUSAttributeType = 14 // RFC2865 5.14. Login-IP-Host
|
|
RADIUSAttributeTypeLoginService RADIUSAttributeType = 15 // RFC2865 5.15. Login-Service
|
|
RADIUSAttributeTypeLoginTCPPort RADIUSAttributeType = 16 // RFC2865 5.16. Login-TCP-Port
|
|
RADIUSAttributeTypeReplyMessage RADIUSAttributeType = 18 // RFC2865 5.18. Reply-Message
|
|
RADIUSAttributeTypeCallbackNumber RADIUSAttributeType = 19 // RFC2865 5.19. Callback-Number
|
|
RADIUSAttributeTypeCallbackId RADIUSAttributeType = 20 // RFC2865 5.20. Callback-Id
|
|
RADIUSAttributeTypeFramedRoute RADIUSAttributeType = 22 // RFC2865 5.22. Framed-Route
|
|
RADIUSAttributeTypeFramedIPXNetwork RADIUSAttributeType = 23 // RFC2865 5.23. Framed-IPX-Network
|
|
RADIUSAttributeTypeState RADIUSAttributeType = 24 // RFC2865 5.24. State
|
|
RADIUSAttributeTypeClass RADIUSAttributeType = 25 // RFC2865 5.25. Class
|
|
RADIUSAttributeTypeVendorSpecific RADIUSAttributeType = 26 // RFC2865 5.26. Vendor-Specific
|
|
RADIUSAttributeTypeSessionTimeout RADIUSAttributeType = 27 // RFC2865 5.27. Session-Timeout
|
|
RADIUSAttributeTypeIdleTimeout RADIUSAttributeType = 28 // RFC2865 5.28. Idle-Timeout
|
|
RADIUSAttributeTypeTerminationAction RADIUSAttributeType = 29 // RFC2865 5.29. Termination-Action
|
|
RADIUSAttributeTypeCalledStationId RADIUSAttributeType = 30 // RFC2865 5.30. Called-Station-Id
|
|
RADIUSAttributeTypeCallingStationId RADIUSAttributeType = 31 // RFC2865 5.31. Calling-Station-Id
|
|
RADIUSAttributeTypeNASIdentifier RADIUSAttributeType = 32 // RFC2865 5.32. NAS-Identifier
|
|
RADIUSAttributeTypeProxyState RADIUSAttributeType = 33 // RFC2865 5.33. Proxy-State
|
|
RADIUSAttributeTypeLoginLATService RADIUSAttributeType = 34 // RFC2865 5.34. Login-LAT-Service
|
|
RADIUSAttributeTypeLoginLATNode RADIUSAttributeType = 35 // RFC2865 5.35. Login-LAT-Node
|
|
RADIUSAttributeTypeLoginLATGroup RADIUSAttributeType = 36 // RFC2865 5.36. Login-LAT-Group
|
|
RADIUSAttributeTypeFramedAppleTalkLink RADIUSAttributeType = 37 // RFC2865 5.37. Framed-AppleTalk-Link
|
|
RADIUSAttributeTypeFramedAppleTalkNetwork RADIUSAttributeType = 38 // RFC2865 5.38. Framed-AppleTalk-Network
|
|
RADIUSAttributeTypeFramedAppleTalkZone RADIUSAttributeType = 39 // RFC2865 5.39. Framed-AppleTalk-Zone
|
|
RADIUSAttributeTypeAcctStatusType RADIUSAttributeType = 40 // RFC2866 5.1. Acct-Status-Type
|
|
RADIUSAttributeTypeAcctDelayTime RADIUSAttributeType = 41 // RFC2866 5.2. Acct-Delay-Time
|
|
RADIUSAttributeTypeAcctInputOctets RADIUSAttributeType = 42 // RFC2866 5.3. Acct-Input-Octets
|
|
RADIUSAttributeTypeAcctOutputOctets RADIUSAttributeType = 43 // RFC2866 5.4. Acct-Output-Octets
|
|
RADIUSAttributeTypeAcctSessionId RADIUSAttributeType = 44 // RFC2866 5.5. Acct-Session-Id
|
|
RADIUSAttributeTypeAcctAuthentic RADIUSAttributeType = 45 // RFC2866 5.6. Acct-Authentic
|
|
RADIUSAttributeTypeAcctSessionTime RADIUSAttributeType = 46 // RFC2866 5.7. Acct-Session-Time
|
|
RADIUSAttributeTypeAcctInputPackets RADIUSAttributeType = 47 // RFC2866 5.8. Acct-Input-Packets
|
|
RADIUSAttributeTypeAcctOutputPackets RADIUSAttributeType = 48 // RFC2866 5.9. Acct-Output-Packets
|
|
RADIUSAttributeTypeAcctTerminateCause RADIUSAttributeType = 49 // RFC2866 5.10. Acct-Terminate-Cause
|
|
RADIUSAttributeTypeAcctMultiSessionId RADIUSAttributeType = 50 // RFC2866 5.11. Acct-Multi-Session-Id
|
|
RADIUSAttributeTypeAcctLinkCount RADIUSAttributeType = 51 // RFC2866 5.12. Acct-Link-Count
|
|
RADIUSAttributeTypeAcctInputGigawords RADIUSAttributeType = 52 // RFC2869 5.1. Acct-Input-Gigawords
|
|
RADIUSAttributeTypeAcctOutputGigawords RADIUSAttributeType = 53 // RFC2869 5.2. Acct-Output-Gigawords
|
|
RADIUSAttributeTypeEventTimestamp RADIUSAttributeType = 55 // RFC2869 5.3. Event-Timestamp
|
|
RADIUSAttributeTypeCHAPChallenge RADIUSAttributeType = 60 // RFC2865 5.40. CHAP-Challenge
|
|
RADIUSAttributeTypeNASPortType RADIUSAttributeType = 61 // RFC2865 5.41. NAS-Port-Type
|
|
RADIUSAttributeTypePortLimit RADIUSAttributeType = 62 // RFC2865 5.42. Port-Limit
|
|
RADIUSAttributeTypeLoginLATPort RADIUSAttributeType = 63 // RFC2865 5.43. Login-LAT-Port
|
|
RADIUSAttributeTypeTunnelType RADIUSAttributeType = 64 // RFC2868 3.1. Tunnel-Type
|
|
RADIUSAttributeTypeTunnelMediumType RADIUSAttributeType = 65 // RFC2868 3.2. Tunnel-Medium-Type
|
|
RADIUSAttributeTypeTunnelClientEndpoint RADIUSAttributeType = 66 // RFC2868 3.3. Tunnel-Client-Endpoint
|
|
RADIUSAttributeTypeTunnelServerEndpoint RADIUSAttributeType = 67 // RFC2868 3.4. Tunnel-Server-Endpoint
|
|
RADIUSAttributeTypeAcctTunnelConnection RADIUSAttributeType = 68 // RFC2867 4.1. Acct-Tunnel-Connection
|
|
RADIUSAttributeTypeTunnelPassword RADIUSAttributeType = 69 // RFC2868 3.5. Tunnel-Password
|
|
RADIUSAttributeTypeARAPPassword RADIUSAttributeType = 70 // RFC2869 5.4. ARAP-Password
|
|
RADIUSAttributeTypeARAPFeatures RADIUSAttributeType = 71 // RFC2869 5.5. ARAP-Features
|
|
RADIUSAttributeTypeARAPZoneAccess RADIUSAttributeType = 72 // RFC2869 5.6. ARAP-Zone-Access
|
|
RADIUSAttributeTypeARAPSecurity RADIUSAttributeType = 73 // RFC2869 5.7. ARAP-Security
|
|
RADIUSAttributeTypeARAPSecurityData RADIUSAttributeType = 74 // RFC2869 5.8. ARAP-Security-Data
|
|
RADIUSAttributeTypePasswordRetry RADIUSAttributeType = 75 // RFC2869 5.9. Password-Retry
|
|
RADIUSAttributeTypePrompt RADIUSAttributeType = 76 // RFC2869 5.10. Prompt
|
|
RADIUSAttributeTypeConnectInfo RADIUSAttributeType = 77 // RFC2869 5.11. Connect-Info
|
|
RADIUSAttributeTypeConfigurationToken RADIUSAttributeType = 78 // RFC2869 5.12. Configuration-Token
|
|
RADIUSAttributeTypeEAPMessage RADIUSAttributeType = 79 // RFC2869 5.13. EAP-Message
|
|
RADIUSAttributeTypeMessageAuthenticator RADIUSAttributeType = 80 // RFC2869 5.14. Message-Authenticator
|
|
RADIUSAttributeTypeTunnelPrivateGroupID RADIUSAttributeType = 81 // RFC2868 3.6. Tunnel-Private-Group-ID
|
|
RADIUSAttributeTypeTunnelAssignmentID RADIUSAttributeType = 82 // RFC2868 3.7. Tunnel-Assignment-ID
|
|
RADIUSAttributeTypeTunnelPreference RADIUSAttributeType = 83 // RFC2868 3.8. Tunnel-Preference
|
|
RADIUSAttributeTypeARAPChallengeResponse RADIUSAttributeType = 84 // RFC2869 5.15. ARAP-Challenge-Response
|
|
RADIUSAttributeTypeAcctInterimInterval RADIUSAttributeType = 85 // RFC2869 5.16. Acct-Interim-Interval
|
|
RADIUSAttributeTypeAcctTunnelPacketsLost RADIUSAttributeType = 86 // RFC2867 4.2. Acct-Tunnel-Packets-Lost
|
|
RADIUSAttributeTypeNASPortId RADIUSAttributeType = 87 // RFC2869 5.17. NAS-Port-Id
|
|
RADIUSAttributeTypeFramedPool RADIUSAttributeType = 88 // RFC2869 5.18. Framed-Pool
|
|
RADIUSAttributeTypeTunnelClientAuthID RADIUSAttributeType = 90 // RFC2868 3.9. Tunnel-Client-Auth-ID
|
|
RADIUSAttributeTypeTunnelServerAuthID RADIUSAttributeType = 91 // RFC2868 3.10. Tunnel-Server-Auth-ID
|
|
)
|
|
|
|
// RADIUSAttributeType represents attribute length.
|
|
type RADIUSAttributeLength uint8
|
|
|
|
// RADIUSAttributeType represents attribute value.
|
|
type RADIUSAttributeValue []byte
|
|
|
|
// String returns a string version of a RADIUSAttributeType.
|
|
func (t RADIUSAttributeType) String() (s string) {
|
|
switch t {
|
|
case RADIUSAttributeTypeUserName:
|
|
s = "User-Name"
|
|
case RADIUSAttributeTypeUserPassword:
|
|
s = "User-Password"
|
|
case RADIUSAttributeTypeCHAPPassword:
|
|
s = "CHAP-Password"
|
|
case RADIUSAttributeTypeNASIPAddress:
|
|
s = "NAS-IP-Address"
|
|
case RADIUSAttributeTypeNASPort:
|
|
s = "NAS-Port"
|
|
case RADIUSAttributeTypeServiceType:
|
|
s = "Service-Type"
|
|
case RADIUSAttributeTypeFramedProtocol:
|
|
s = "Framed-Protocol"
|
|
case RADIUSAttributeTypeFramedIPAddress:
|
|
s = "Framed-IP-Address"
|
|
case RADIUSAttributeTypeFramedIPNetmask:
|
|
s = "Framed-IP-Netmask"
|
|
case RADIUSAttributeTypeFramedRouting:
|
|
s = "Framed-Routing"
|
|
case RADIUSAttributeTypeFilterId:
|
|
s = "Filter-Id"
|
|
case RADIUSAttributeTypeFramedMTU:
|
|
s = "Framed-MTU"
|
|
case RADIUSAttributeTypeFramedCompression:
|
|
s = "Framed-Compression"
|
|
case RADIUSAttributeTypeLoginIPHost:
|
|
s = "Login-IP-Host"
|
|
case RADIUSAttributeTypeLoginService:
|
|
s = "Login-Service"
|
|
case RADIUSAttributeTypeLoginTCPPort:
|
|
s = "Login-TCP-Port"
|
|
case RADIUSAttributeTypeReplyMessage:
|
|
s = "Reply-Message"
|
|
case RADIUSAttributeTypeCallbackNumber:
|
|
s = "Callback-Number"
|
|
case RADIUSAttributeTypeCallbackId:
|
|
s = "Callback-Id"
|
|
case RADIUSAttributeTypeFramedRoute:
|
|
s = "Framed-Route"
|
|
case RADIUSAttributeTypeFramedIPXNetwork:
|
|
s = "Framed-IPX-Network"
|
|
case RADIUSAttributeTypeState:
|
|
s = "State"
|
|
case RADIUSAttributeTypeClass:
|
|
s = "Class"
|
|
case RADIUSAttributeTypeVendorSpecific:
|
|
s = "Vendor-Specific"
|
|
case RADIUSAttributeTypeSessionTimeout:
|
|
s = "Session-Timeout"
|
|
case RADIUSAttributeTypeIdleTimeout:
|
|
s = "Idle-Timeout"
|
|
case RADIUSAttributeTypeTerminationAction:
|
|
s = "Termination-Action"
|
|
case RADIUSAttributeTypeCalledStationId:
|
|
s = "Called-Station-Id"
|
|
case RADIUSAttributeTypeCallingStationId:
|
|
s = "Calling-Station-Id"
|
|
case RADIUSAttributeTypeNASIdentifier:
|
|
s = "NAS-Identifier"
|
|
case RADIUSAttributeTypeProxyState:
|
|
s = "Proxy-State"
|
|
case RADIUSAttributeTypeLoginLATService:
|
|
s = "Login-LAT-Service"
|
|
case RADIUSAttributeTypeLoginLATNode:
|
|
s = "Login-LAT-Node"
|
|
case RADIUSAttributeTypeLoginLATGroup:
|
|
s = "Login-LAT-Group"
|
|
case RADIUSAttributeTypeFramedAppleTalkLink:
|
|
s = "Framed-AppleTalk-Link"
|
|
case RADIUSAttributeTypeFramedAppleTalkNetwork:
|
|
s = "Framed-AppleTalk-Network"
|
|
case RADIUSAttributeTypeFramedAppleTalkZone:
|
|
s = "Framed-AppleTalk-Zone"
|
|
case RADIUSAttributeTypeAcctStatusType:
|
|
s = "Acct-Status-Type"
|
|
case RADIUSAttributeTypeAcctDelayTime:
|
|
s = "Acct-Delay-Time"
|
|
case RADIUSAttributeTypeAcctInputOctets:
|
|
s = "Acct-Input-Octets"
|
|
case RADIUSAttributeTypeAcctOutputOctets:
|
|
s = "Acct-Output-Octets"
|
|
case RADIUSAttributeTypeAcctSessionId:
|
|
s = "Acct-Session-Id"
|
|
case RADIUSAttributeTypeAcctAuthentic:
|
|
s = "Acct-Authentic"
|
|
case RADIUSAttributeTypeAcctSessionTime:
|
|
s = "Acct-Session-Time"
|
|
case RADIUSAttributeTypeAcctInputPackets:
|
|
s = "Acct-Input-Packets"
|
|
case RADIUSAttributeTypeAcctOutputPackets:
|
|
s = "Acct-Output-Packets"
|
|
case RADIUSAttributeTypeAcctTerminateCause:
|
|
s = "Acct-Terminate-Cause"
|
|
case RADIUSAttributeTypeAcctMultiSessionId:
|
|
s = "Acct-Multi-Session-Id"
|
|
case RADIUSAttributeTypeAcctLinkCount:
|
|
s = "Acct-Link-Count"
|
|
case RADIUSAttributeTypeAcctInputGigawords:
|
|
s = "Acct-Input-Gigawords"
|
|
case RADIUSAttributeTypeAcctOutputGigawords:
|
|
s = "Acct-Output-Gigawords"
|
|
case RADIUSAttributeTypeEventTimestamp:
|
|
s = "Event-Timestamp"
|
|
case RADIUSAttributeTypeCHAPChallenge:
|
|
s = "CHAP-Challenge"
|
|
case RADIUSAttributeTypeNASPortType:
|
|
s = "NAS-Port-Type"
|
|
case RADIUSAttributeTypePortLimit:
|
|
s = "Port-Limit"
|
|
case RADIUSAttributeTypeLoginLATPort:
|
|
s = "Login-LAT-Port"
|
|
case RADIUSAttributeTypeTunnelType:
|
|
s = "Tunnel-Type"
|
|
case RADIUSAttributeTypeTunnelMediumType:
|
|
s = "Tunnel-Medium-Type"
|
|
case RADIUSAttributeTypeTunnelClientEndpoint:
|
|
s = "Tunnel-Client-Endpoint"
|
|
case RADIUSAttributeTypeTunnelServerEndpoint:
|
|
s = "Tunnel-Server-Endpoint"
|
|
case RADIUSAttributeTypeAcctTunnelConnection:
|
|
s = "Acct-Tunnel-Connection"
|
|
case RADIUSAttributeTypeTunnelPassword:
|
|
s = "Tunnel-Password"
|
|
case RADIUSAttributeTypeARAPPassword:
|
|
s = "ARAP-Password"
|
|
case RADIUSAttributeTypeARAPFeatures:
|
|
s = "ARAP-Features"
|
|
case RADIUSAttributeTypeARAPZoneAccess:
|
|
s = "ARAP-Zone-Access"
|
|
case RADIUSAttributeTypeARAPSecurity:
|
|
s = "ARAP-Security"
|
|
case RADIUSAttributeTypeARAPSecurityData:
|
|
s = "ARAP-Security-Data"
|
|
case RADIUSAttributeTypePasswordRetry:
|
|
s = "Password-Retry"
|
|
case RADIUSAttributeTypePrompt:
|
|
s = "Prompt"
|
|
case RADIUSAttributeTypeConnectInfo:
|
|
s = "Connect-Info"
|
|
case RADIUSAttributeTypeConfigurationToken:
|
|
s = "Configuration-Token"
|
|
case RADIUSAttributeTypeEAPMessage:
|
|
s = "EAP-Message"
|
|
case RADIUSAttributeTypeMessageAuthenticator:
|
|
s = "Message-Authenticator"
|
|
case RADIUSAttributeTypeTunnelPrivateGroupID:
|
|
s = "Tunnel-Private-Group-ID"
|
|
case RADIUSAttributeTypeTunnelAssignmentID:
|
|
s = "Tunnel-Assignment-ID"
|
|
case RADIUSAttributeTypeTunnelPreference:
|
|
s = "Tunnel-Preference"
|
|
case RADIUSAttributeTypeARAPChallengeResponse:
|
|
s = "ARAP-Challenge-Response"
|
|
case RADIUSAttributeTypeAcctInterimInterval:
|
|
s = "Acct-Interim-Interval"
|
|
case RADIUSAttributeTypeAcctTunnelPacketsLost:
|
|
s = "Acct-Tunnel-Packets-Lost"
|
|
case RADIUSAttributeTypeNASPortId:
|
|
s = "NAS-Port-Id"
|
|
case RADIUSAttributeTypeFramedPool:
|
|
s = "Framed-Pool"
|
|
case RADIUSAttributeTypeTunnelClientAuthID:
|
|
s = "Tunnel-Client-Auth-ID"
|
|
case RADIUSAttributeTypeTunnelServerAuthID:
|
|
s = "Tunnel-Server-Auth-ID"
|
|
default:
|
|
s = fmt.Sprintf("Unknown(%d)", t)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Len returns the length of a RADIUS packet.
|
|
func (radius *RADIUS) Len() (int, error) {
|
|
n := radiusMinimumRecordSizeInBytes
|
|
for _, v := range radius.Attributes {
|
|
alen, err := attributeValueLength(v.Value)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
n += int(alen) + 2 // Added Type and Length
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// LayerType returns LayerTypeRADIUS.
|
|
func (radius *RADIUS) LayerType() gopacket.LayerType {
|
|
return LayerTypeRADIUS
|
|
}
|
|
|
|
// DecodeFromBytes decodes the given bytes into this layer.
|
|
func (radius *RADIUS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
|
if len(data) > radiusMaximumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS length %d too big", len(data))
|
|
}
|
|
|
|
if len(data) < radiusMinimumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS length %d too short", len(data))
|
|
}
|
|
|
|
radius.BaseLayer = BaseLayer{Contents: data}
|
|
|
|
radius.Code = RADIUSCode(data[0])
|
|
radius.Identifier = RADIUSIdentifier(data[1])
|
|
radius.Length = RADIUSLength(binary.BigEndian.Uint16(data[2:4]))
|
|
|
|
if int(radius.Length) > radiusMaximumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS length %d too big", radius.Length)
|
|
}
|
|
|
|
if int(radius.Length) < radiusMinimumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS length %d too short", radius.Length)
|
|
}
|
|
|
|
// RFC 2865 3. Packet Format
|
|
// `If the packet is shorter than the Length field indicates, it MUST be silently discarded.`
|
|
if int(radius.Length) > len(data) {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS length %d too big", radius.Length)
|
|
}
|
|
|
|
// RFC 2865 3. Packet Format
|
|
// `Octets outside the range of the Length field MUST be treated as padding and ignored on reception.`
|
|
if int(radius.Length) < len(data) {
|
|
df.SetTruncated()
|
|
data = data[:radius.Length]
|
|
}
|
|
|
|
copy(radius.Authenticator[:], data[4:20])
|
|
|
|
if len(data) == radiusMinimumRecordSizeInBytes {
|
|
return nil
|
|
}
|
|
|
|
pos := radiusMinimumRecordSizeInBytes
|
|
for {
|
|
if len(data) == pos {
|
|
break
|
|
}
|
|
|
|
if len(data[pos:]) < radiusAttributesMinimumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS attributes length %d too short", len(data[pos:]))
|
|
}
|
|
|
|
attr := RADIUSAttribute{}
|
|
attr.Type = RADIUSAttributeType(data[pos])
|
|
attr.Length = RADIUSAttributeLength(data[pos+1])
|
|
|
|
if int(attr.Length) > len(data[pos:]) {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS attributes length %d too big", attr.Length)
|
|
}
|
|
|
|
if int(attr.Length) < radiusAttributesMinimumRecordSizeInBytes {
|
|
df.SetTruncated()
|
|
return fmt.Errorf("RADIUS attributes length %d too short", attr.Length)
|
|
}
|
|
|
|
if int(attr.Length) > radiusAttributesMinimumRecordSizeInBytes {
|
|
attr.Value = make([]byte, attr.Length-2)
|
|
copy(attr.Value[:], data[pos+2:pos+int(attr.Length)])
|
|
radius.Attributes = append(radius.Attributes, attr)
|
|
}
|
|
|
|
pos += int(attr.Length)
|
|
}
|
|
|
|
for _, v := range radius.Attributes {
|
|
if v.Type == RADIUSAttributeTypeEAPMessage {
|
|
radius.BaseLayer.Payload = append(radius.BaseLayer.Payload, v.Value...)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SerializeTo writes the serialized form of this layer into the
|
|
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
|
// See the docs for gopacket.SerializableLayer for more info.
|
|
func (radius *RADIUS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
|
plen, err := radius.Len()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if opts.FixLengths {
|
|
radius.Length = RADIUSLength(plen)
|
|
}
|
|
|
|
data, err := b.PrependBytes(plen)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data[0] = byte(radius.Code)
|
|
data[1] = byte(radius.Identifier)
|
|
binary.BigEndian.PutUint16(data[2:], uint16(radius.Length))
|
|
copy(data[4:20], radius.Authenticator[:])
|
|
|
|
pos := radiusMinimumRecordSizeInBytes
|
|
for _, v := range radius.Attributes {
|
|
if opts.FixLengths {
|
|
v.Length, err = attributeValueLength(v.Value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
data[pos] = byte(v.Type)
|
|
data[pos+1] = byte(v.Length)
|
|
copy(data[pos+2:], v.Value[:])
|
|
|
|
pos += len(v.Value) + 2 // Added Type and Length
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
|
func (radius *RADIUS) CanDecode() gopacket.LayerClass {
|
|
return LayerTypeRADIUS
|
|
}
|
|
|
|
// NextLayerType returns the layer type contained by this DecodingLayer.
|
|
func (radius *RADIUS) NextLayerType() gopacket.LayerType {
|
|
if len(radius.BaseLayer.Payload) > 0 {
|
|
return LayerTypeEAP
|
|
} else {
|
|
return gopacket.LayerTypeZero
|
|
}
|
|
}
|
|
|
|
// Payload returns the EAP Type-Data for EAP-Message attributes.
|
|
func (radius *RADIUS) Payload() []byte {
|
|
return radius.BaseLayer.Payload
|
|
}
|
|
|
|
func decodeRADIUS(data []byte, p gopacket.PacketBuilder) error {
|
|
radius := &RADIUS{}
|
|
err := radius.DecodeFromBytes(data, p)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p.AddLayer(radius)
|
|
p.SetApplicationLayer(radius)
|
|
next := radius.NextLayerType()
|
|
if next == gopacket.LayerTypeZero {
|
|
return nil
|
|
}
|
|
return p.NextDecoder(next)
|
|
}
|
|
|
|
func attributeValueLength(v []byte) (RADIUSAttributeLength, error) {
|
|
n := len(v)
|
|
if n > 255 {
|
|
return 0, fmt.Errorf("RADIUS attribute value length %d too long", n)
|
|
} else {
|
|
return RADIUSAttributeLength(n), nil
|
|
}
|
|
}
|