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