/src/PcapPlusPlus/Packet++/header/RadiusLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "TLVData.h" |
5 | | |
6 | | /// @file |
7 | | |
8 | | /** |
9 | | * \namespace pcpp |
10 | | * \brief The main namespace for the PcapPlusPlus lib |
11 | | */ |
12 | | namespace pcpp |
13 | | { |
14 | | |
15 | | /** |
16 | | * @struct radius_header |
17 | | * Represents a RADIUS protocol header |
18 | | */ |
19 | | #pragma pack(push, 1) |
20 | | struct radius_header |
21 | | { |
22 | | /** RADIUS message code */ |
23 | | uint8_t code; |
24 | | /** RADIUS message ID */ |
25 | | uint8_t id; |
26 | | /** RADIUS message length */ |
27 | | uint16_t length; |
28 | | /** Used to authenticate the reply from the RADIUS server and to encrypt passwords */ |
29 | | uint8_t authenticator[16]; |
30 | | }; |
31 | | #pragma pack(pop) |
32 | | |
33 | | |
34 | | /** |
35 | | * @class RadiusAttribute |
36 | | * A wrapper class for RADIUS attributes. This class does not create or modify RADIUS attribute records, but rather |
37 | | * serves as a wrapper and provides useful methods for retrieving data from them |
38 | | */ |
39 | | class RadiusAttribute : public TLVRecord<uint8_t, uint8_t> |
40 | | { |
41 | | public: |
42 | | |
43 | | /** |
44 | | * A c'tor for this class that gets a pointer to the attribute raw data (byte array) |
45 | | * @param[in] attrRawData A pointer to the attribute raw data |
46 | | */ |
47 | 0 | explicit RadiusAttribute(uint8_t* attrRawData) : TLVRecord(attrRawData) { } |
48 | | |
49 | | /** |
50 | | * A d'tor for this class, currently does nothing |
51 | | */ |
52 | 0 | virtual ~RadiusAttribute() { } |
53 | | |
54 | | // implement abstract methods |
55 | | |
56 | | size_t getTotalSize() const |
57 | 0 | { |
58 | 0 | if (m_Data == nullptr) |
59 | 0 | return 0; |
60 | | |
61 | 0 | return (size_t)m_Data->recordLen; |
62 | 0 | } |
63 | | |
64 | | size_t getDataSize() const |
65 | 0 | { |
66 | 0 | if (m_Data == nullptr) |
67 | 0 | return 0; |
68 | | |
69 | 0 | return (size_t)m_Data->recordLen - 2*sizeof(uint8_t); |
70 | 0 | } |
71 | | }; |
72 | | |
73 | | |
74 | | /** |
75 | | * @class RadiusAttributeBuilder |
76 | | * A class for building RADIUS attributes. This builder receives the attribute parameters in its c'tor, |
77 | | * builds the RADIUS attribute raw buffer and provides a build() method to get a RadiusAttribute object out of it |
78 | | */ |
79 | | class RadiusAttributeBuilder : public TLVRecordBuilder |
80 | | { |
81 | | public: |
82 | | |
83 | | /** |
84 | | * A c'tor for building RADIUS attributes which their value is a byte array. The RadiusAttribute object can later |
85 | | * be retrieved by calling build() |
86 | | * @param[in] attrType RADIUS attribute type |
87 | | * @param[in] attrValue A buffer containing the attribute value. This buffer is read-only and isn't modified in any way |
88 | | * @param[in] attrValueLen Attribute value length in bytes |
89 | | */ |
90 | | RadiusAttributeBuilder(uint8_t attrType, const uint8_t* attrValue, uint8_t attrValueLen) : |
91 | 0 | TLVRecordBuilder(attrType, attrValue, attrValueLen) { } |
92 | | |
93 | | /** |
94 | | * A c'tor for building RADIUS attributes which have a 1-byte value. The RadiusAttribute object can later be retrieved |
95 | | * by calling build() |
96 | | * @param[in] attrType RADIUS attribute type |
97 | | * @param[in] attrValue A 1-byte attribute value |
98 | | */ |
99 | | RadiusAttributeBuilder(uint8_t attrType, uint8_t attrValue) : |
100 | 0 | TLVRecordBuilder(attrType, attrValue) { } |
101 | | |
102 | | /** |
103 | | * A c'tor for building RADIUS attributes which have a 2-byte value. The RadiusAttribute object can later be retrieved |
104 | | * by calling build() |
105 | | * @param[in] attrType RADIUS attribute type |
106 | | * @param[in] attrValue A 2-byte attribute value |
107 | | */ |
108 | | RadiusAttributeBuilder(uint8_t attrType, uint16_t attrValue) : |
109 | 0 | TLVRecordBuilder(attrType, attrValue) { } |
110 | | |
111 | | /** |
112 | | * A c'tor for building RADIUS attributes which have a 4-byte value. The RadiusAttribute object can later be retrieved |
113 | | * by calling build() |
114 | | * @param[in] attrType RADIUS attribute type |
115 | | * @param[in] attrValue A 4-byte attribute value |
116 | | */ |
117 | | RadiusAttributeBuilder(uint8_t attrType, uint32_t attrValue) : |
118 | 0 | TLVRecordBuilder(attrType, attrValue) { } |
119 | | |
120 | | /** |
121 | | * A c'tor for building RADIUS attributes which have an IPv4Address value. The RadiusAttribute object can later be |
122 | | * retrieved by calling build() |
123 | | * @param[in] attrType RADIUS attribute type |
124 | | * @param[in] attrValue The IPv4 address attribute value |
125 | | */ |
126 | | RadiusAttributeBuilder(uint8_t attrType, const IPv4Address& attrValue) : |
127 | 0 | TLVRecordBuilder(attrType, attrValue) { } |
128 | | |
129 | | /** |
130 | | * A c'tor for building RADIUS attributes which have a string value. The RadiusAttribute object can later be retrieved |
131 | | * by calling build() |
132 | | * @param[in] attrType RADIUS attribute type |
133 | | * @param[in] attrValue The string attribute value |
134 | | */ |
135 | | RadiusAttributeBuilder(uint8_t attrType, const std::string& attrValue) : |
136 | 0 | TLVRecordBuilder(attrType, attrValue) { } |
137 | | |
138 | | /** |
139 | | * A copy c'tor which copies all the data from another instance of RadiusAttributeBuilder |
140 | | * @param[in] other The instance to copy from |
141 | | */ |
142 | | RadiusAttributeBuilder(const RadiusAttributeBuilder& other) : |
143 | 0 | TLVRecordBuilder(other) { } |
144 | | |
145 | | /** |
146 | | * Assignment operator that copies all data from another instance of RadiusAttributeBuilder |
147 | | * @param[in] other The instance to assign from |
148 | | */ |
149 | | RadiusAttributeBuilder& operator=(const RadiusAttributeBuilder& other) |
150 | 0 | { |
151 | 0 | TLVRecordBuilder::operator=(other); |
152 | 0 | return *this; |
153 | 0 | } |
154 | | |
155 | | /** |
156 | | * Build the RadiusAttribute object out of the parameters defined in the c'tor |
157 | | * @return The RadiusAttribute object |
158 | | */ |
159 | | RadiusAttribute build() const; |
160 | | }; |
161 | | |
162 | | |
163 | | /** |
164 | | * @class RadiusLayer |
165 | | * Represents a RADIUS (Remote Authentication Dial-In User Service) protocol layer |
166 | | */ |
167 | | class RadiusLayer : public Layer |
168 | | { |
169 | | private: |
170 | | |
171 | | TLVRecordReader<RadiusAttribute> m_AttributeReader; |
172 | | |
173 | 0 | uint8_t* getAttributesBasePtr() const { return m_Data + sizeof(radius_header); } |
174 | | |
175 | | RadiusAttribute addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset); |
176 | | |
177 | | public: |
178 | | |
179 | | /** |
180 | | * A constructor that creates the layer from an existing packet raw data |
181 | | * @param[in] data A pointer to the raw data |
182 | | * @param[in] dataLen Size of the data in bytes |
183 | | * @param[in] prevLayer A pointer to the previous layer |
184 | | * @param[in] packet A pointer to the Packet instance where layer will be stored in |
185 | | */ |
186 | | RadiusLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : |
187 | | Layer(data, dataLen, prevLayer, packet) |
188 | 1.37k | { m_Protocol = Radius; } |
189 | | |
190 | | /** |
191 | | * A constructor that creates a new layer from scratch |
192 | | * @param[in] code The RADIUS message code |
193 | | * @param[in] id The RADIUS message ID |
194 | | * @param[in] authenticator A pointer to a byte array containing the authenticator value |
195 | | * @param[in] authenticatorArrSize The authenticator byte array size. A valid size of the authenticator field is |
196 | | * 16 bytes. If the provided size is less than that then the byte array will be copied to the packet but the missing |
197 | | * bytes will stay zero. If the size is more than 16 bytes, only the first 16 bytes will be copied to the packet |
198 | | */ |
199 | | RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize); |
200 | | |
201 | | /** |
202 | | * A constructor that creates a new layer from scratch |
203 | | * @param[in] code The RADIUS message code |
204 | | * @param[in] id The RADIUS message ID |
205 | | * @param[in] authenticator A hex string representing the authenticator value. A valid size of the authenticator |
206 | | * field is 16 bytes. If the hex string represents an array that is smaller than this then the missing bytes in the |
207 | | * packet's authenticator field will stay zero. If the hex string represents an array that is larger than 16 bytes, |
208 | | * only the first 16 bytes will be copied to the packet |
209 | | */ |
210 | | RadiusLayer(uint8_t code, uint8_t id, const std::string &authenticator); |
211 | | |
212 | | /** |
213 | | * A d'tor for this layer, currently does nothing |
214 | | */ |
215 | 1.37k | ~RadiusLayer() {} |
216 | | |
217 | | /** |
218 | | * Get a pointer to the RADIUS header. Notice this points directly to the data, so every change will change the actual packet data |
219 | | * @return A pointer to the radius_header object |
220 | | */ |
221 | 2.81k | radius_header* getRadiusHeader() const { return (radius_header*)m_Data; } |
222 | | |
223 | | /** |
224 | | * @return A hex string representation of the radius_header#authenticator byte array value |
225 | | */ |
226 | | std::string getAuthenticatorValue() const; |
227 | | |
228 | | /** |
229 | | * Setter for radius_header#authenticator |
230 | | * @param[in] authValue A hex string representing the requested authenticator value |
231 | | */ |
232 | | void setAuthenticatorValue(const std::string& authValue); |
233 | | |
234 | | /** |
235 | | * A static method that returns the RADIUS message string for a give message code. For example: the string |
236 | | * "Access-Request" will be returned for code 1 |
237 | | * @param[in] radiusMessageCode RADIUS message code |
238 | | * @return RADIUS message string |
239 | | */ |
240 | | static std::string getRadiusMessageString(uint8_t radiusMessageCode); |
241 | | |
242 | | /** |
243 | | * @return The first RADIUS attribute in the packet. If there are no attributes the returned value will contain |
244 | | * a logical NULL (RadiusAttribute#isNull() == true) |
245 | | */ |
246 | | RadiusAttribute getFirstAttribute() const; |
247 | | |
248 | | /** |
249 | | * Get the RADIUS attribute that comes after a given attribute. If the given attribute was the last one, the |
250 | | * returned value will contain a logical NULL (RadiusAttribute#isNull() == true) |
251 | | * @param[in] attr A given attribute |
252 | | * @return A RadiusAttribute object containing the attribute data that comes next, or logical NULL if the given |
253 | | * attribute: (1) was the last one; (2) contains a logical NULL or (3) doesn't belong to this packet |
254 | | */ |
255 | | RadiusAttribute getNextAttribute(RadiusAttribute& attr) const; |
256 | | |
257 | | /** |
258 | | * Get a RADIUS attribute by attribute type |
259 | | * @param[in] attrType RADIUS attribute type |
260 | | * @return A RadiusAttribute object containing the first attribute data that matches this type, or logical NULL |
261 | | * (RadiusAttribute#isNull() == true) if no such attribute found |
262 | | */ |
263 | | RadiusAttribute getAttribute(uint8_t attrType) const; |
264 | | |
265 | | /** |
266 | | * @return The number of RADIUS attributes in the packet |
267 | | */ |
268 | | size_t getAttributeCount() const; |
269 | | |
270 | | /** |
271 | | * Add a new RADIUS attribute at the end of the layer |
272 | | * @param[in] attrBuilder A RadiusAttributeBuilder object that contains the requested attribute data to add |
273 | | * @return A RadiusAttribute object containing the newly added RADIUS attribute data or logical NULL |
274 | | * (RadiusAttribute#isNull() == true) if addition failed |
275 | | */ |
276 | | RadiusAttribute addAttribute(const RadiusAttributeBuilder& attrBuilder); |
277 | | |
278 | | /** |
279 | | * Add a new RADIUS attribute after an existing one |
280 | | * @param[in] attrBuilder A RadiusAttributeBuilder object that contains the requested attribute data to add |
281 | | * @param[in] prevAttrType The RADIUS attribute which the newly added attribute will come after |
282 | | * @return A RadiusAttribute object containing the newly added RADIUS attribute data or logical NULL |
283 | | * (RadiusAttribute#isNull() == true) if addition failed |
284 | | */ |
285 | | RadiusAttribute addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType); |
286 | | |
287 | | /** |
288 | | * Remove an existing RADIUS attribute from the layer |
289 | | * @param[in] attrType The RADIUS attribute type to remove |
290 | | * @return True if the RADIUS attribute was successfully removed or false if type wasn't found or if removal failed |
291 | | */ |
292 | | bool removeAttribute(uint8_t attrType); |
293 | | |
294 | | /** |
295 | | * Remove all RADIUS attributes in this layer |
296 | | * @return True if all attributes were successfully removed or false if removal failed for some reason |
297 | | */ |
298 | | bool removeAllAttributes(); |
299 | | |
300 | | /** |
301 | | * The static method makes validation of UDP data |
302 | | * @param[in] udpData The pointer to the UDP payload data. It points to the first byte of RADIUS header. |
303 | | * @param[in] udpDataLen The payload data size |
304 | | * @return True if the data is valid and can represent the RADIUS packet |
305 | | */ |
306 | | static bool isDataValid(const uint8_t* udpData, size_t udpDataLen); |
307 | | |
308 | | /** |
309 | | * A static method that checks whether the port is considered as RADIUS |
310 | | * @param[in] port The port number to be checked |
311 | | */ |
312 | | static inline bool isRadiusPort(uint16_t port); |
313 | | |
314 | | // implement abstract methods |
315 | | |
316 | | /** |
317 | | * @return The size written in radius_header#length |
318 | | */ |
319 | | size_t getHeaderLen() const; |
320 | | |
321 | | /** |
322 | | * Does nothing for this layer, RADIUS is always last |
323 | | */ |
324 | 1.37k | void parseNextLayer() {} |
325 | | |
326 | | /** |
327 | | * Calculate and store the value of radius_header#length according to the layer size |
328 | | */ |
329 | | void computeCalculateFields(); |
330 | | |
331 | | std::string toString() const; |
332 | | |
333 | 281 | OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } |
334 | | }; |
335 | | |
336 | | |
337 | | // implementation of inline methods |
338 | | |
339 | | bool RadiusLayer::isRadiusPort(uint16_t port) |
340 | 255k | { |
341 | 255k | switch (port) |
342 | 255k | { |
343 | 16 | case 1812: |
344 | 20.4k | case 1813: |
345 | 26.5k | case 3799: |
346 | 26.5k | return true; |
347 | 228k | default: |
348 | 228k | return false; |
349 | 255k | } |
350 | 255k | } // isRadiusPort |
351 | | |
352 | | } // namespace pcpp |