blob: c43ea2945168eaca8c2c8e69f9321dce0848f28f [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301// 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
6package layers
7
8import (
9 "encoding/binary"
10 "fmt"
11
12 "github.com/google/gopacket"
13)
14
15const (
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.
28type 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.
39type RADIUSCode uint8
40
41// constants that define RADIUSCode.
42const (
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.
55func (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.
82type RADIUSIdentifier uint8
83
84// RADIUSLength represents packet length.
85type RADIUSLength uint16
86
87// RADIUSAuthenticator represents authenticator.
88type RADIUSAuthenticator [16]byte
89
90// RADIUSAttribute represents attributes.
91type RADIUSAttribute struct {
92 Type RADIUSAttributeType
93 Length RADIUSAttributeLength
94 Value RADIUSAttributeValue
95}
96
97// RADIUSAttributeType represents attribute type.
98type RADIUSAttributeType uint8
99
100// constants that define RADIUSAttributeType.
101const (
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.
188type RADIUSAttributeLength uint8
189
190// RADIUSAttributeType represents attribute value.
191type RADIUSAttributeValue []byte
192
193// String returns a string version of a RADIUSAttributeType.
194func (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.
369func (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.
382func (radius *RADIUS) LayerType() gopacket.LayerType {
383 return LayerTypeRADIUS
384}
385
386// DecodeFromBytes decodes the given bytes into this layer.
387func (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.
480func (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.
520func (radius *RADIUS) CanDecode() gopacket.LayerClass {
521 return LayerTypeRADIUS
522}
523
524// NextLayerType returns the layer type contained by this DecodingLayer.
525func (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.
534func (radius *RADIUS) Payload() []byte {
535 return radius.BaseLayer.Payload
536}
537
538func 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
553func 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}