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  }