radius.go 22 KB

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