/src/PcapPlusPlus/Packet++/src/RadiusLayer.cpp
Line | Count | Source |
1 | 0 | #define LOG_MODULE PacketLogModuleRadiusLayer |
2 | | #include "RadiusLayer.h" |
3 | | #include "Logger.h" |
4 | | #include "GeneralUtils.h" |
5 | | #include <sstream> |
6 | | #include "EndianPortable.h" |
7 | | |
8 | | namespace pcpp |
9 | | { |
10 | | |
11 | | RadiusAttribute RadiusAttributeBuilder::build() const |
12 | 0 | { |
13 | 0 | size_t recSize = m_RecValueLen + 2; |
14 | 0 | uint8_t* recordBuffer = new uint8_t[recSize]; |
15 | 0 | memset(recordBuffer, 0, recSize); |
16 | 0 | recordBuffer[0] = static_cast<uint8_t>(m_RecType); |
17 | 0 | recordBuffer[1] = static_cast<uint8_t>(recSize); |
18 | 0 | if (m_RecValueLen > 0) |
19 | 0 | memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); |
20 | |
|
21 | 0 | return RadiusAttribute(recordBuffer); |
22 | 0 | } |
23 | | |
24 | | RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize) |
25 | 0 | { |
26 | 0 | allocData(sizeof(radius_header)); |
27 | 0 | m_Protocol = Radius; |
28 | |
|
29 | 0 | radius_header* hdr = getRadiusHeader(); |
30 | 0 | hdr->code = code; |
31 | 0 | hdr->id = id; |
32 | 0 | hdr->length = htobe16(sizeof(radius_header)); |
33 | 0 | if (authenticatorArrSize == 0 || authenticator == nullptr) |
34 | 0 | return; |
35 | 0 | if (authenticatorArrSize > 16) |
36 | 0 | authenticatorArrSize = 16; |
37 | 0 | memcpy(hdr->authenticator, authenticator, authenticatorArrSize); |
38 | 0 | } |
39 | | |
40 | | RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const std::string& authenticator) |
41 | 0 | { |
42 | 0 | allocData(sizeof(radius_header)); |
43 | 0 | m_Protocol = Radius; |
44 | |
|
45 | 0 | radius_header* hdr = getRadiusHeader(); |
46 | 0 | hdr->code = code; |
47 | 0 | hdr->id = id; |
48 | 0 | hdr->length = htobe16(sizeof(radius_header)); |
49 | 0 | setAuthenticatorValue(authenticator); |
50 | 0 | } |
51 | | |
52 | | RadiusAttribute RadiusLayer::addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset) |
53 | 0 | { |
54 | 0 | RadiusAttribute newAttr = attrBuilder.build(); |
55 | 0 | if (newAttr.isNull()) |
56 | 0 | { |
57 | 0 | PCPP_LOG_ERROR("Cannot build new attribute of type " << (int)newAttr.getType()); |
58 | 0 | return newAttr; |
59 | 0 | } |
60 | | |
61 | 0 | size_t sizeToExtend = newAttr.getTotalSize(); |
62 | 0 | if (!extendLayer(offset, sizeToExtend)) |
63 | 0 | { |
64 | 0 | PCPP_LOG_ERROR("Could not extend RadiusLayer in [" << newAttr.getTotalSize() << "] bytes"); |
65 | 0 | newAttr.purgeRecordData(); |
66 | 0 | return RadiusAttribute(nullptr); |
67 | 0 | } |
68 | | |
69 | 0 | memcpy(m_Data + offset, newAttr.getRecordBasePtr(), newAttr.getTotalSize()); |
70 | |
|
71 | 0 | uint8_t* newAttrPtr = m_Data + offset; |
72 | |
|
73 | 0 | m_AttributeReader.changeTLVRecordCount(1); |
74 | |
|
75 | 0 | newAttr.purgeRecordData(); |
76 | |
|
77 | 0 | getRadiusHeader()->length = htobe16(m_DataLen); |
78 | |
|
79 | 0 | return RadiusAttribute(newAttrPtr); |
80 | 0 | } |
81 | | |
82 | | std::string RadiusLayer::getAuthenticatorValue() const |
83 | 0 | { |
84 | 0 | return byteArrayToHexString(getRadiusHeader()->authenticator, 16); |
85 | 0 | } |
86 | | |
87 | | void RadiusLayer::setAuthenticatorValue(const std::string& authValue) |
88 | 0 | { |
89 | 0 | hexStringToByteArray(authValue, getRadiusHeader()->authenticator, 16); |
90 | 0 | } |
91 | | |
92 | | std::string RadiusLayer::getRadiusMessageString(uint8_t radiusMessageCode) |
93 | 9.14k | { |
94 | 9.14k | switch (radiusMessageCode) |
95 | 9.14k | { |
96 | 2.45k | case 1: |
97 | 2.45k | return "Access-Request"; |
98 | 582 | case 2: |
99 | 582 | return "Access-Accept"; |
100 | 656 | case 3: |
101 | 656 | return "Access-Reject"; |
102 | 198 | case 4: |
103 | 198 | return "Accounting-Request"; |
104 | 86 | case 5: |
105 | 86 | return "Accounting-Response"; |
106 | 1.45k | case 11: |
107 | 1.45k | return "Access-Challenge"; |
108 | 0 | case 12: |
109 | 0 | return "Status-Server"; |
110 | 0 | case 13: |
111 | 0 | return "Status-Client"; |
112 | 1.93k | case 40: |
113 | 1.93k | return "Disconnect-Request"; |
114 | 1.23k | case 41: |
115 | 1.23k | return "Disconnect-ACK"; |
116 | 186 | case 42: |
117 | 186 | return "Disconnect-NAK"; |
118 | 0 | case 43: |
119 | 0 | return "CoA-Request"; |
120 | 114 | case 44: |
121 | 114 | return "CoA-ACK"; |
122 | 0 | case 45: |
123 | 0 | return "CoA-NAK"; |
124 | 32 | case 255: |
125 | 32 | return "Reserved"; |
126 | 214 | default: |
127 | 214 | return "Unknown"; |
128 | 9.14k | } |
129 | 9.14k | } |
130 | | |
131 | | size_t RadiusLayer::getHeaderLen() const |
132 | 4.57k | { |
133 | 4.57k | uint16_t len = be16toh(getRadiusHeader()->length); |
134 | 4.57k | if (len > m_DataLen) |
135 | 0 | return m_DataLen; |
136 | | |
137 | 4.57k | return len; |
138 | 4.57k | } |
139 | | |
140 | | void RadiusLayer::computeCalculateFields() |
141 | 4.57k | { |
142 | 4.57k | getRadiusHeader()->length = htobe16(m_DataLen); |
143 | 4.57k | } |
144 | | |
145 | | std::string RadiusLayer::toString() const |
146 | 9.14k | { |
147 | 9.14k | std::ostringstream str; |
148 | 9.14k | str << "RADIUS Layer, " << RadiusLayer::getRadiusMessageString(getRadiusHeader()->code) << "(" |
149 | 9.14k | << (int)getRadiusHeader()->code |
150 | 9.14k | << "), " |
151 | 9.14k | "Id=" |
152 | 9.14k | << (int)getRadiusHeader()->id << ", " |
153 | 9.14k | << "Length=" << be16toh(getRadiusHeader()->length); |
154 | | |
155 | 9.14k | return str.str(); |
156 | 9.14k | } |
157 | | |
158 | | RadiusAttribute RadiusLayer::getFirstAttribute() const |
159 | 0 | { |
160 | 0 | return m_AttributeReader.getFirstTLVRecord(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); |
161 | 0 | } |
162 | | |
163 | | RadiusAttribute RadiusLayer::getNextAttribute(RadiusAttribute& attr) const |
164 | 0 | { |
165 | 0 | return m_AttributeReader.getNextTLVRecord(attr, getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); |
166 | 0 | } |
167 | | |
168 | | RadiusAttribute RadiusLayer::getAttribute(uint8_t attributeType) const |
169 | 0 | { |
170 | 0 | return m_AttributeReader.getTLVRecord(attributeType, getAttributesBasePtr(), |
171 | 0 | getHeaderLen() - sizeof(radius_header)); |
172 | 0 | } |
173 | | |
174 | | size_t RadiusLayer::getAttributeCount() const |
175 | 0 | { |
176 | 0 | return m_AttributeReader.getTLVRecordCount(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); |
177 | 0 | } |
178 | | |
179 | | RadiusAttribute RadiusLayer::addAttribute(const RadiusAttributeBuilder& attrBuilder) |
180 | 0 | { |
181 | 0 | int offset = getHeaderLen(); |
182 | 0 | return addAttrAt(attrBuilder, offset); |
183 | 0 | } |
184 | | |
185 | | RadiusAttribute RadiusLayer::addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType) |
186 | 0 | { |
187 | 0 | int offset = 0; |
188 | |
|
189 | 0 | RadiusAttribute prevAttr = getAttribute(prevAttrType); |
190 | |
|
191 | 0 | if (prevAttr.isNull()) |
192 | 0 | { |
193 | 0 | offset = getHeaderLen(); |
194 | 0 | } |
195 | 0 | else |
196 | 0 | { |
197 | 0 | offset = prevAttr.getRecordBasePtr() + prevAttr.getTotalSize() - m_Data; |
198 | 0 | } |
199 | |
|
200 | 0 | return addAttrAt(attrBuilder, offset); |
201 | 0 | } |
202 | | |
203 | | bool RadiusLayer::removeAttribute(uint8_t attrType) |
204 | 0 | { |
205 | 0 | RadiusAttribute attrToRemove = getAttribute(attrType); |
206 | 0 | if (attrToRemove.isNull()) |
207 | 0 | { |
208 | 0 | return false; |
209 | 0 | } |
210 | | |
211 | 0 | int offset = attrToRemove.getRecordBasePtr() - m_Data; |
212 | |
|
213 | 0 | if (!shortenLayer(offset, attrToRemove.getTotalSize())) |
214 | 0 | { |
215 | 0 | return false; |
216 | 0 | } |
217 | | |
218 | 0 | m_AttributeReader.changeTLVRecordCount(-1); |
219 | 0 | getRadiusHeader()->length = htobe16(m_DataLen); |
220 | |
|
221 | 0 | return true; |
222 | 0 | } |
223 | | |
224 | | bool RadiusLayer::removeAllAttributes() |
225 | 0 | { |
226 | 0 | int offset = sizeof(radius_header); |
227 | |
|
228 | 0 | if (!shortenLayer(offset, getHeaderLen() - offset)) |
229 | 0 | return false; |
230 | | |
231 | 0 | m_AttributeReader.changeTLVRecordCount(0 - getAttributeCount()); |
232 | |
|
233 | 0 | getRadiusHeader()->length = htobe16(m_DataLen); |
234 | |
|
235 | 0 | return true; |
236 | 0 | } |
237 | | |
238 | | bool RadiusLayer::isDataValid(const uint8_t* udpData, size_t udpDataLen) |
239 | 29.9k | { |
240 | 29.9k | if (udpData != nullptr && udpDataLen >= sizeof(radius_header)) |
241 | 29.7k | { |
242 | 29.7k | const radius_header* radHdr = reinterpret_cast<const radius_header*>(udpData); |
243 | 29.7k | size_t radLen = be16toh(radHdr->length); |
244 | 29.7k | return radLen >= sizeof(radius_header) && radLen <= udpDataLen; |
245 | 29.7k | } |
246 | 140 | return false; |
247 | 29.9k | } |
248 | | |
249 | | } // namespace pcpp |