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