cloudflared-mirror/vendor/github.com/google/gopacket/layers/radius.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
}
}