/src/PcapPlusPlus/Packet++/src/LdapLayer.cpp
Line | Count | Source |
1 | | #include "LdapLayer.h" |
2 | | #include "GeneralUtils.h" |
3 | | #include <unordered_map> |
4 | | |
5 | | namespace pcpp |
6 | | { |
7 | | |
8 | | constexpr uint8_t LdapResponseLayer::referralTagType; |
9 | | constexpr int LdapBindResponseLayer::serverSaslCredentialsTagType; |
10 | | |
11 | | // region LdapOperationType |
12 | | |
13 | | // clang-format off |
14 | | static const std::unordered_map<LdapOperationType::Value, std::string, EnumClassHash<LdapOperationType::Value>> LdapOperationTypeToString{ |
15 | | { LdapOperationType::BindRequest, "BindRequest" }, |
16 | | { LdapOperationType::BindResponse, "BindResponse" }, |
17 | | { LdapOperationType::UnbindRequest, "UnbindRequest" }, |
18 | | { LdapOperationType::SearchRequest, "SearchRequest" }, |
19 | | { LdapOperationType::SearchResultEntry, "SearchResultEntry" }, |
20 | | { LdapOperationType::SearchResultDone, "SearchResultDone" }, |
21 | | { LdapOperationType::ModifyRequest, "ModifyRequest" }, |
22 | | { LdapOperationType::ModifyResponse, "ModifyResponse" }, |
23 | | { LdapOperationType::AddRequest, "AddRequest" }, |
24 | | { LdapOperationType::AddResponse, "AddResponse" }, |
25 | | { LdapOperationType::DeleteRequest, "DeleteRequest" }, |
26 | | { LdapOperationType::DeleteResponse, "DeleteResponse" }, |
27 | | { LdapOperationType::ModifyDNRequest, "ModifyDNRequest" }, |
28 | | { LdapOperationType::ModifyDNResponse, "ModifyDNResponse" }, |
29 | | { LdapOperationType::CompareRequest, "CompareRequest" }, |
30 | | { LdapOperationType::CompareResponse, "CompareResponse" }, |
31 | | { LdapOperationType::AbandonRequest, "AbandonRequest" }, |
32 | | { LdapOperationType::SearchResultReference, "SearchResultReference" }, |
33 | | { LdapOperationType::ExtendedRequest, "ExtendedRequest" }, |
34 | | { LdapOperationType::ExtendedResponse, "ExtendedResponse" }, |
35 | | { LdapOperationType::IntermediateResponse, "IntermediateResponse" }, |
36 | | { LdapOperationType::Unknown, "Unknown" } |
37 | | }; |
38 | | // clang-format on |
39 | | |
40 | | static const std::unordered_map<uint8_t, LdapOperationType> UintToLdapOperationType{ |
41 | | { static_cast<uint8_t>(LdapOperationType::BindRequest), LdapOperationType::BindRequest }, |
42 | | { static_cast<uint8_t>(LdapOperationType::BindResponse), LdapOperationType::BindResponse }, |
43 | | { static_cast<uint8_t>(LdapOperationType::UnbindRequest), LdapOperationType::UnbindRequest }, |
44 | | { static_cast<uint8_t>(LdapOperationType::SearchRequest), LdapOperationType::SearchRequest }, |
45 | | { static_cast<uint8_t>(LdapOperationType::SearchResultEntry), LdapOperationType::SearchResultEntry }, |
46 | | { static_cast<uint8_t>(LdapOperationType::SearchResultDone), LdapOperationType::SearchResultDone }, |
47 | | { static_cast<uint8_t>(LdapOperationType::ModifyResponse), LdapOperationType::ModifyResponse }, |
48 | | { static_cast<uint8_t>(LdapOperationType::AddRequest), LdapOperationType::AddRequest }, |
49 | | { static_cast<uint8_t>(LdapOperationType::AddResponse), LdapOperationType::AddResponse }, |
50 | | { static_cast<uint8_t>(LdapOperationType::DeleteRequest), LdapOperationType::DeleteRequest }, |
51 | | { static_cast<uint8_t>(LdapOperationType::DeleteResponse), LdapOperationType::DeleteResponse }, |
52 | | { static_cast<uint8_t>(LdapOperationType::ModifyDNRequest), LdapOperationType::ModifyDNRequest }, |
53 | | { static_cast<uint8_t>(LdapOperationType::ModifyDNResponse), LdapOperationType::ModifyDNResponse }, |
54 | | { static_cast<uint8_t>(LdapOperationType::CompareRequest), LdapOperationType::CompareRequest }, |
55 | | { static_cast<uint8_t>(LdapOperationType::CompareResponse), LdapOperationType::CompareResponse }, |
56 | | { static_cast<uint8_t>(LdapOperationType::AbandonRequest), LdapOperationType::AbandonRequest }, |
57 | | { static_cast<uint8_t>(LdapOperationType::SearchResultReference), LdapOperationType::SearchResultReference }, |
58 | | { static_cast<uint8_t>(LdapOperationType::ExtendedRequest), LdapOperationType::ExtendedRequest }, |
59 | | { static_cast<uint8_t>(LdapOperationType::ExtendedResponse), LdapOperationType::ExtendedResponse }, |
60 | | { static_cast<uint8_t>(LdapOperationType::IntermediateResponse), LdapOperationType::IntermediateResponse } |
61 | | }; |
62 | | |
63 | | std::string LdapOperationType::toString() const |
64 | 16.0k | { |
65 | 16.0k | return LdapOperationTypeToString.at(m_Value); |
66 | 16.0k | } |
67 | | |
68 | | LdapOperationType LdapOperationType::fromUintValue(uint8_t value) |
69 | 66.1k | { |
70 | 66.1k | auto result = UintToLdapOperationType.find(value); |
71 | 66.1k | if (result != UintToLdapOperationType.end()) |
72 | 65.6k | { |
73 | 65.6k | return result->second; |
74 | 65.6k | } |
75 | | |
76 | 468 | return LdapOperationType::Unknown; |
77 | 66.1k | } |
78 | | |
79 | | // endregion |
80 | | |
81 | | // region LdapResultCode |
82 | | |
83 | | // clang-format off |
84 | | static const std::unordered_map<LdapResultCode::Value, std::string, EnumClassHash<LdapResultCode::Value>> LdapResultCodeToString{ |
85 | | { LdapResultCode::Success, "Success" }, |
86 | | { LdapResultCode::OperationsError, "OperationsError" }, |
87 | | { LdapResultCode::ProtocolError, "ProtocolError" }, |
88 | | { LdapResultCode::TimeLimitExceeded, "TimeLimitExceeded" }, |
89 | | { LdapResultCode::SizeLimitExceeded, "SizeLimitExceeded" }, |
90 | | { LdapResultCode::CompareFalse, "CompareFalse" }, |
91 | | { LdapResultCode::CompareTrue, "CompareTrue" }, |
92 | | { LdapResultCode::AuthMethodNotSupported, "AuthMethodNotSupported" }, |
93 | | { LdapResultCode::StrongerAuthRequired, "StrongerAuthRequired" }, |
94 | | { LdapResultCode::Referral, "Referral" }, |
95 | | { LdapResultCode::AdminLimitExceeded, "AdminLimitExceeded" }, |
96 | | { LdapResultCode::UnavailableCriticalExtension, "UnavailableCriticalExtension" }, |
97 | | { LdapResultCode::ConfidentialityRequired, "ConfidentialityRequired" }, |
98 | | { LdapResultCode::SaslBindInProgress, "SaslBindInProgress" }, |
99 | | { LdapResultCode::NoSuchAttribute, "NoSuchAttribute" }, |
100 | | { LdapResultCode::UndefinedAttributeType, "UndefinedAttributeType" }, |
101 | | { LdapResultCode::InappropriateMatching, "InappropriateMatching" }, |
102 | | { LdapResultCode::ConstraintViolation, "ConstraintViolation" }, |
103 | | { LdapResultCode::AttributeOrValueExists, "AttributeOrValueExists" }, |
104 | | { LdapResultCode::InvalidAttributeSyntax, "InvalidAttributeSyntax" }, |
105 | | { LdapResultCode::NoSuchObject, "NoSuchObject" }, |
106 | | { LdapResultCode::AliasProblem, "AliasProblem" }, |
107 | | { LdapResultCode::InvalidDNSyntax, "InvalidDNSyntax" }, |
108 | | { LdapResultCode::AliasDereferencingProblem, "AliasDereferencingProblem" }, |
109 | | { LdapResultCode::InappropriateAuthentication, "InappropriateAuthentication" }, |
110 | | { LdapResultCode::InvalidCredentials, "InvalidCredentials" }, |
111 | | { LdapResultCode::InsufficientAccessRights, "InsufficientAccessRights" }, |
112 | | { LdapResultCode::Busy, "Busy" }, |
113 | | { LdapResultCode::Unavailable, "Unavailable" }, |
114 | | { LdapResultCode::UnwillingToPerform, "UnwillingToPerform" }, |
115 | | { LdapResultCode::LoopDetect, "LoopDetect" }, |
116 | | { LdapResultCode::NamingViolation, "NamingViolation" }, |
117 | | { LdapResultCode::ObjectClassViolation, "ObjectClassViolation" }, |
118 | | { LdapResultCode::NotAllowedOnNonLeaf, "NotAllowedOnNonLeaf" }, |
119 | | { LdapResultCode::NotAllowedOnRDN, "NotAllowedOnRDN" }, |
120 | | { LdapResultCode::EntryAlreadyExists, "EntryAlreadyExists" }, |
121 | | { LdapResultCode::ObjectClassModsProhibited, "ObjectClassModsProhibited" }, |
122 | | { LdapResultCode::AffectsMultipleDSAs, "AffectsMultipleDSAs" }, |
123 | | { LdapResultCode::Other, "Other" } |
124 | | }; |
125 | | // clang-format on |
126 | | |
127 | | // clang-format off |
128 | | static const std::unordered_map<uint8_t, LdapResultCode> UintToLdapResultCode{ |
129 | | { static_cast<uint8_t>(LdapResultCode::Success), LdapResultCode::Success }, |
130 | | { static_cast<uint8_t>(LdapResultCode::OperationsError), LdapResultCode::OperationsError }, |
131 | | { static_cast<uint8_t>(LdapResultCode::ProtocolError), LdapResultCode::ProtocolError }, |
132 | | { static_cast<uint8_t>(LdapResultCode::TimeLimitExceeded), LdapResultCode::TimeLimitExceeded }, |
133 | | { static_cast<uint8_t>(LdapResultCode::SizeLimitExceeded), LdapResultCode::SizeLimitExceeded }, |
134 | | { static_cast<uint8_t>(LdapResultCode::CompareFalse), LdapResultCode::CompareFalse }, |
135 | | { static_cast<uint8_t>(LdapResultCode::CompareTrue), LdapResultCode::CompareTrue }, |
136 | | { static_cast<uint8_t>(LdapResultCode::AuthMethodNotSupported), LdapResultCode::AuthMethodNotSupported }, |
137 | | { static_cast<uint8_t>(LdapResultCode::StrongerAuthRequired), LdapResultCode::StrongerAuthRequired }, |
138 | | { static_cast<uint8_t>(LdapResultCode::Referral), LdapResultCode::Referral }, |
139 | | { static_cast<uint8_t>(LdapResultCode::AdminLimitExceeded), LdapResultCode::AdminLimitExceeded }, |
140 | | { static_cast<uint8_t>(LdapResultCode::UnavailableCriticalExtension), LdapResultCode::UnavailableCriticalExtension }, |
141 | | { static_cast<uint8_t>(LdapResultCode::ConfidentialityRequired), LdapResultCode::ConfidentialityRequired }, |
142 | | { static_cast<uint8_t>(LdapResultCode::SaslBindInProgress), LdapResultCode::SaslBindInProgress }, |
143 | | { static_cast<uint8_t>(LdapResultCode::NoSuchAttribute), LdapResultCode::NoSuchAttribute }, |
144 | | { static_cast<uint8_t>(LdapResultCode::UndefinedAttributeType), LdapResultCode::UndefinedAttributeType }, |
145 | | { static_cast<uint8_t>(LdapResultCode::InappropriateMatching), LdapResultCode::InappropriateMatching }, |
146 | | { static_cast<uint8_t>(LdapResultCode::ConstraintViolation), LdapResultCode::ConstraintViolation }, |
147 | | { static_cast<uint8_t>(LdapResultCode::AttributeOrValueExists), LdapResultCode::AttributeOrValueExists }, |
148 | | { static_cast<uint8_t>(LdapResultCode::InvalidAttributeSyntax), LdapResultCode::InvalidAttributeSyntax }, |
149 | | { static_cast<uint8_t>(LdapResultCode::NoSuchObject), LdapResultCode::NoSuchObject }, |
150 | | { static_cast<uint8_t>(LdapResultCode::AliasProblem), LdapResultCode::AliasProblem }, |
151 | | { static_cast<uint8_t>(LdapResultCode::InvalidDNSyntax), LdapResultCode::InvalidDNSyntax }, |
152 | | { static_cast<uint8_t>(LdapResultCode::AliasDereferencingProblem), LdapResultCode::AliasDereferencingProblem }, |
153 | | { static_cast<uint8_t>(LdapResultCode::InappropriateAuthentication), LdapResultCode::InappropriateAuthentication }, |
154 | | { static_cast<uint8_t>(LdapResultCode::InvalidCredentials), LdapResultCode::InvalidCredentials }, |
155 | | { static_cast<uint8_t>(LdapResultCode::InsufficientAccessRights), LdapResultCode::InsufficientAccessRights }, |
156 | | { static_cast<uint8_t>(LdapResultCode::Busy), LdapResultCode::Busy }, |
157 | | { static_cast<uint8_t>(LdapResultCode::Unavailable), LdapResultCode::Unavailable }, |
158 | | { static_cast<uint8_t>(LdapResultCode::UnwillingToPerform), LdapResultCode::UnwillingToPerform }, |
159 | | { static_cast<uint8_t>(LdapResultCode::LoopDetect), LdapResultCode::LoopDetect }, |
160 | | { static_cast<uint8_t>(LdapResultCode::NamingViolation), LdapResultCode::NamingViolation }, |
161 | | { static_cast<uint8_t>(LdapResultCode::ObjectClassViolation), LdapResultCode::ObjectClassViolation }, |
162 | | { static_cast<uint8_t>(LdapResultCode::NotAllowedOnNonLeaf), LdapResultCode::NotAllowedOnNonLeaf }, |
163 | | { static_cast<uint8_t>(LdapResultCode::NotAllowedOnRDN), LdapResultCode::NotAllowedOnRDN }, |
164 | | { static_cast<uint8_t>(LdapResultCode::EntryAlreadyExists), LdapResultCode::EntryAlreadyExists }, |
165 | | { static_cast<uint8_t>(LdapResultCode::ObjectClassModsProhibited), LdapResultCode::ObjectClassModsProhibited }, |
166 | | { static_cast<uint8_t>(LdapResultCode::AffectsMultipleDSAs), LdapResultCode::AffectsMultipleDSAs }, |
167 | | { static_cast<uint8_t>(LdapResultCode::Other), LdapResultCode::Other } |
168 | | }; |
169 | | // clang-format on |
170 | | |
171 | | std::string LdapResultCode::toString() const |
172 | 4.23k | { |
173 | 4.23k | return LdapResultCodeToString.at(m_Value); |
174 | 4.23k | } |
175 | | |
176 | | LdapResultCode LdapResultCode::fromUintValue(uint8_t value) |
177 | 4.23k | { |
178 | 4.23k | auto result = UintToLdapResultCode.find(value); |
179 | 4.23k | if (result != UintToLdapResultCode.end()) |
180 | 4.23k | { |
181 | 4.23k | return result->second; |
182 | 4.23k | } |
183 | | |
184 | 0 | return LdapResultCode::Unknown; |
185 | 4.23k | } |
186 | | |
187 | | // endregion |
188 | | |
189 | | // region LdapLayer |
190 | | |
191 | | LdapLayer::LdapLayer(uint16_t messageId, LdapOperationType operationType, |
192 | | const std::vector<Asn1Record*>& messageRecords, const std::vector<LdapControl>& controls) |
193 | 0 | { |
194 | 0 | init(messageId, operationType, messageRecords, controls); |
195 | 0 | } |
196 | | |
197 | | LdapLayer::LdapLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
198 | | Packet* packet) |
199 | 51.3k | : Layer(data, dataLen, prevLayer, packet, LDAP) |
200 | 51.3k | { |
201 | 51.3k | m_Asn1Record = std::move(asn1Record); |
202 | 51.3k | } |
203 | | |
204 | | void LdapLayer::init(uint16_t messageId, LdapOperationType operationType, |
205 | | const std::vector<Asn1Record*>& messageRecords, const std::vector<LdapControl>& controls) |
206 | 0 | { |
207 | 0 | Asn1IntegerRecord messageIdRecord(messageId); |
208 | 0 | std::unique_ptr<Asn1Record> messageRootRecord; |
209 | 0 | if (!messageRecords.empty()) |
210 | 0 | { |
211 | 0 | messageRootRecord = |
212 | 0 | std::make_unique<Asn1ConstructedRecord>(Asn1TagClass::Application, operationType, messageRecords); |
213 | 0 | } |
214 | 0 | else |
215 | 0 | { |
216 | 0 | messageRootRecord = |
217 | 0 | std::make_unique<Asn1GenericRecord>(Asn1TagClass::Application, false, operationType, ""); |
218 | 0 | } |
219 | |
|
220 | 0 | std::vector<Asn1Record*> rootSubRecords = { &messageIdRecord, messageRootRecord.get() }; |
221 | |
|
222 | 0 | std::unique_ptr<Asn1ConstructedRecord> controlsRecord; |
223 | 0 | if (!controls.empty()) |
224 | 0 | { |
225 | 0 | PointerVector<Asn1Record> controlsSubRecords; |
226 | 0 | for (const auto& control : controls) |
227 | 0 | { |
228 | 0 | Asn1OctetStringRecord controlTypeRecord(control.controlType); |
229 | 0 | if (control.controlValue.empty()) |
230 | 0 | { |
231 | 0 | controlsSubRecords.pushBack(new Asn1SequenceRecord({ &controlTypeRecord })); |
232 | 0 | } |
233 | 0 | else |
234 | 0 | { |
235 | 0 | auto controlValueSize = static_cast<size_t>(control.controlValue.size() / 2); |
236 | 0 | std::unique_ptr<uint8_t[]> controlValue = std::make_unique<uint8_t[]>(controlValueSize); |
237 | 0 | controlValueSize = hexStringToByteArray(control.controlValue, controlValue.get(), controlValueSize); |
238 | 0 | Asn1OctetStringRecord controlValueRecord(controlValue.get(), controlValueSize); |
239 | 0 | controlsSubRecords.pushBack(new Asn1SequenceRecord({ &controlTypeRecord, &controlValueRecord })); |
240 | 0 | } |
241 | 0 | } |
242 | 0 | controlsRecord = |
243 | 0 | std::make_unique<Asn1ConstructedRecord>(Asn1TagClass::ContextSpecific, 0, controlsSubRecords); |
244 | 0 | rootSubRecords.push_back(controlsRecord.get()); |
245 | 0 | } |
246 | |
|
247 | 0 | Asn1SequenceRecord rootRecord(rootSubRecords); |
248 | |
|
249 | 0 | auto encodedData = rootRecord.encode(); |
250 | 0 | m_DataLen = encodedData.size(); |
251 | 0 | m_Data = new uint8_t[m_DataLen]; |
252 | 0 | std::copy(encodedData.begin(), encodedData.end(), m_Data); |
253 | 0 | m_Protocol = LDAP; |
254 | 0 | m_Asn1Record = Asn1Record::decode(m_Data, m_DataLen, true); |
255 | 0 | } |
256 | | |
257 | | std::string LdapLayer::toString() const |
258 | 16.0k | { |
259 | 16.0k | auto extendedInfo = getExtendedInfoString(); |
260 | 16.0k | return "LDAP Layer, " + getLdapOperationType().toString() + (extendedInfo.empty() ? "" : ", " + extendedInfo); |
261 | 16.0k | } |
262 | | |
263 | | LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) |
264 | 57.1k | { |
265 | 57.1k | try |
266 | 57.1k | { |
267 | 57.1k | auto asn1Record = Asn1Record::decode(data, dataLen, true); |
268 | 57.1k | auto operationType = LdapOperationType::fromUintValue( |
269 | 57.1k | asn1Record->castAs<Asn1SequenceRecord>()->getSubRecords().at(operationTypeIndex)->getTagType()); |
270 | 57.1k | switch (operationType) |
271 | 57.1k | { |
272 | 3.49k | case LdapOperationType::BindRequest: |
273 | 3.49k | return new LdapBindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
274 | 1.98k | case LdapOperationType::BindResponse: |
275 | 1.98k | return new LdapBindResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
276 | 4.25k | case LdapOperationType::UnbindRequest: |
277 | 4.25k | return new LdapUnbindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
278 | 2.66k | case LdapOperationType::SearchRequest: |
279 | 2.66k | return new LdapSearchRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
280 | 839 | case LdapOperationType::SearchResultEntry: |
281 | 839 | return new LdapSearchResultEntryLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
282 | 7.23k | case LdapOperationType::SearchResultDone: |
283 | 7.23k | return new LdapSearchResultDoneLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
284 | 955 | case LdapOperationType::ModifyResponse: |
285 | 955 | return new LdapModifyResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
286 | 30 | case LdapOperationType::AddResponse: |
287 | 30 | return new LdapAddResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
288 | 80 | case LdapOperationType::DeleteResponse: |
289 | 80 | return new LdapDeleteResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
290 | 1.79k | case LdapOperationType::ModifyDNResponse: |
291 | 1.79k | return new LdapModifyDNResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
292 | 1.04k | case LdapOperationType::CompareResponse: |
293 | 1.04k | return new LdapCompareResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
294 | 340 | case LdapOperationType::Unknown: |
295 | 340 | return nullptr; |
296 | 27.0k | default: |
297 | 27.0k | return new LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); |
298 | 57.1k | } |
299 | 57.1k | } |
300 | 57.1k | catch (...) |
301 | 57.1k | { |
302 | 5.37k | return nullptr; |
303 | 5.37k | } |
304 | 57.1k | } |
305 | | |
306 | | Asn1SequenceRecord* LdapLayer::getRootAsn1Record() const |
307 | 23.5k | { |
308 | 23.5k | return m_Asn1Record->castAs<Asn1SequenceRecord>(); |
309 | 23.5k | } |
310 | | |
311 | | Asn1ConstructedRecord* LdapLayer::getLdapOperationAsn1Record() const |
312 | 23.5k | { |
313 | 23.5k | return getRootAsn1Record()->getSubRecords().at(operationTypeIndex)->castAs<Asn1ConstructedRecord>(); |
314 | 23.5k | } |
315 | | |
316 | | uint16_t LdapLayer::getMessageID() const |
317 | 0 | { |
318 | 0 | return getRootAsn1Record() |
319 | 0 | ->getSubRecords() |
320 | 0 | .at(messageIdIndex) |
321 | 0 | ->castAs<Asn1IntegerRecord>() |
322 | 0 | ->getIntValue<uint16_t>(); |
323 | 0 | } |
324 | | |
325 | | std::vector<LdapControl> LdapLayer::getControls() const |
326 | 0 | { |
327 | 0 | std::vector<LdapControl> controls; |
328 | 0 | if (getRootAsn1Record()->getSubRecords().size() <= controlsIndex) |
329 | 0 | { |
330 | 0 | return controls; |
331 | 0 | } |
332 | | |
333 | 0 | auto controlsRecord = getRootAsn1Record()->getSubRecords().at(controlsIndex)->castAs<Asn1ConstructedRecord>(); |
334 | 0 | for (auto controlRecord : controlsRecord->getSubRecords()) |
335 | 0 | { |
336 | 0 | auto controlSequence = controlRecord->castAs<Asn1SequenceRecord>(); |
337 | 0 | auto controlType = |
338 | 0 | controlSequence->getSubRecords().at(controlTypeIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
339 | 0 | std::string controlValue; |
340 | 0 | if (controlSequence->getSubRecords().size() > controlValueIndex) |
341 | 0 | { |
342 | 0 | controlValue = |
343 | 0 | controlSequence->getSubRecords().at(controlValueIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
344 | 0 | } |
345 | 0 | controls.push_back({ controlType, controlValue }); |
346 | 0 | } |
347 | |
|
348 | 0 | return controls; |
349 | 0 | } |
350 | | |
351 | | LdapOperationType LdapLayer::getLdapOperationType() const |
352 | 14.3k | { |
353 | 14.3k | uint8_t tagType; |
354 | 14.3k | try |
355 | 14.3k | { |
356 | 14.3k | tagType = getLdapOperationAsn1Record()->getTagType(); |
357 | 14.3k | } |
358 | 14.3k | catch (...) |
359 | 14.3k | { |
360 | 128 | tagType = LdapOperationType::Unknown; |
361 | 128 | } |
362 | | |
363 | 14.3k | return LdapOperationType::fromUintValue(tagType); |
364 | 14.3k | } |
365 | | |
366 | | void LdapLayer::parseNextLayer() |
367 | 51.3k | { |
368 | 51.3k | size_t headerLen = getHeaderLen(); |
369 | 51.3k | if (m_DataLen <= headerLen || headerLen == 0) |
370 | 25.9k | return; |
371 | | |
372 | 25.4k | uint8_t* payload = m_Data + headerLen; |
373 | 25.4k | size_t payloadLen = m_DataLen - headerLen; |
374 | | |
375 | 25.4k | m_NextLayer = LdapLayer::parseLdapMessage(payload, payloadLen, this, m_Packet); |
376 | 25.4k | } |
377 | | // endregion |
378 | | |
379 | | // region LdapResponseLayer |
380 | | |
381 | | LdapResponseLayer::LdapResponseLayer(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, |
382 | | const std::string& matchedDN, const std::string& diagnosticMessage, |
383 | | const std::vector<std::string>& referral, |
384 | | const std::vector<LdapControl>& controls) |
385 | 0 | { |
386 | 0 | LdapResponseLayer::init(messageId, operationType, resultCode, matchedDN, diagnosticMessage, referral, {}, |
387 | 0 | controls); |
388 | 0 | } |
389 | | |
390 | | void LdapResponseLayer::init(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, |
391 | | const std::string& matchedDN, const std::string& diagnosticMessage, |
392 | | const std::vector<std::string>& referral, |
393 | | const std::vector<Asn1Record*>& additionalRecords, |
394 | | const std::vector<LdapControl>& controls) |
395 | 0 | { |
396 | 0 | Asn1EnumeratedRecord resultCodeRecord(resultCode); |
397 | 0 | Asn1OctetStringRecord matchedDNRecord(matchedDN); |
398 | 0 | Asn1OctetStringRecord diagnosticMessageRecord(diagnosticMessage); |
399 | |
|
400 | 0 | std::vector<Asn1Record*> messageRecords = { &resultCodeRecord, &matchedDNRecord, &diagnosticMessageRecord }; |
401 | |
|
402 | 0 | std::unique_ptr<Asn1ConstructedRecord> referralRecord; |
403 | 0 | if (!referral.empty()) |
404 | 0 | { |
405 | 0 | PointerVector<Asn1Record> referralSubRecords; |
406 | 0 | for (const auto& uri : referral) |
407 | 0 | { |
408 | 0 | referralSubRecords.pushBack(new Asn1OctetStringRecord(uri)); |
409 | 0 | } |
410 | 0 | referralRecord = std::make_unique<Asn1ConstructedRecord>(Asn1TagClass::ContextSpecific, referralTagType, |
411 | 0 | referralSubRecords); |
412 | 0 | messageRecords.push_back(referralRecord.get()); |
413 | 0 | } |
414 | |
|
415 | 0 | if (!additionalRecords.empty()) |
416 | 0 | { |
417 | 0 | for (auto additionalRecord : additionalRecords) |
418 | 0 | { |
419 | 0 | messageRecords.push_back(additionalRecord); |
420 | 0 | } |
421 | 0 | } |
422 | |
|
423 | 0 | LdapLayer::init(messageId, operationType, messageRecords, controls); |
424 | 0 | } |
425 | | |
426 | | LdapResultCode LdapResponseLayer::getResultCode() const |
427 | 4.23k | { |
428 | 4.23k | return LdapResultCode::fromUintValue(getLdapOperationAsn1Record() |
429 | 4.23k | ->getSubRecords() |
430 | 4.23k | .at(resultCodeIndex) |
431 | 4.23k | ->castAs<Asn1EnumeratedRecord>() |
432 | 4.23k | ->getIntValue<uint8_t>()); |
433 | 4.23k | } |
434 | | |
435 | | std::string LdapResponseLayer::getMatchedDN() const |
436 | 0 | { |
437 | 0 | return getLdapOperationAsn1Record() |
438 | 0 | ->getSubRecords() |
439 | 0 | .at(matchedDNIndex) |
440 | 0 | ->castAs<Asn1OctetStringRecord>() |
441 | 0 | ->getValue(); |
442 | 0 | } |
443 | | |
444 | | std::string LdapResponseLayer::getDiagnosticMessage() const |
445 | 0 | { |
446 | 0 | return getLdapOperationAsn1Record() |
447 | 0 | ->getSubRecords() |
448 | 0 | .at(diagnotsticsMessageIndex) |
449 | 0 | ->castAs<Asn1OctetStringRecord>() |
450 | 0 | ->getValue(); |
451 | 0 | } |
452 | | |
453 | | std::vector<std::string> LdapResponseLayer::getReferral() const |
454 | 0 | { |
455 | 0 | std::vector<std::string> result; |
456 | 0 | if (getLdapOperationAsn1Record()->getSubRecords().size() <= referralIndex) |
457 | 0 | { |
458 | 0 | return result; |
459 | 0 | } |
460 | | |
461 | 0 | auto referralRecord = getLdapOperationAsn1Record()->getSubRecords().at(referralIndex); |
462 | 0 | if (referralRecord->getTagClass() != Asn1TagClass::ContextSpecific || |
463 | 0 | referralRecord->getTagType() != referralTagType) |
464 | 0 | { |
465 | 0 | return result; |
466 | 0 | } |
467 | | |
468 | 0 | for (auto uriRecord : referralRecord->castAs<Asn1ConstructedRecord>()->getSubRecords()) |
469 | 0 | { |
470 | 0 | result.push_back(uriRecord->castAs<Asn1OctetStringRecord>()->getValue()); |
471 | 0 | } |
472 | |
|
473 | 0 | return result; |
474 | 0 | } |
475 | | |
476 | | std::string LdapResponseLayer::getExtendedInfoString() const |
477 | 4.23k | { |
478 | 4.23k | return getResultCode().toString(); |
479 | 4.23k | } |
480 | | // endregion |
481 | | |
482 | | // region LdapBindRequestLayer |
483 | | |
484 | | LdapBindRequestLayer::LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, |
485 | | const std::string& simpleAuthentication, |
486 | | const std::vector<LdapControl>& controls) |
487 | 0 | { |
488 | 0 | Asn1IntegerRecord versionRecord(version); |
489 | 0 | Asn1OctetStringRecord nameRecord(name); |
490 | 0 | std::vector<Asn1Record*> messageRecords = { &versionRecord, &nameRecord }; |
491 | 0 | std::unique_ptr<Asn1GenericRecord> simpleAuthenticationRecord; |
492 | 0 | if (!simpleAuthentication.empty()) |
493 | 0 | { |
494 | 0 | auto data = reinterpret_cast<const uint8_t*>(simpleAuthentication.data()); |
495 | 0 | simpleAuthenticationRecord = std::make_unique<Asn1GenericRecord>( |
496 | 0 | Asn1TagClass::ContextSpecific, false, |
497 | 0 | static_cast<uint8_t>(LdapBindRequestLayer::AuthenticationType::Simple), data, |
498 | 0 | simpleAuthentication.size()); |
499 | 0 | messageRecords.push_back(simpleAuthenticationRecord.get()); |
500 | 0 | } |
501 | |
|
502 | 0 | LdapLayer::init(messageId, LdapOperationType::BindRequest, messageRecords, controls); |
503 | 0 | } |
504 | | |
505 | | LdapBindRequestLayer::LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, |
506 | | const SaslAuthentication& saslAuthentication, |
507 | | const std::vector<LdapControl>& controls) |
508 | 0 | { |
509 | 0 | Asn1IntegerRecord versionRecord(version); |
510 | 0 | Asn1OctetStringRecord nameRecord(name); |
511 | 0 | std::vector<Asn1Record*> messageRecords = { &versionRecord, &nameRecord }; |
512 | 0 | std::unique_ptr<Asn1ConstructedRecord> saslAuthenticationRecord; |
513 | 0 | if (!saslAuthentication.mechanism.empty()) |
514 | 0 | { |
515 | 0 | PointerVector<Asn1Record> saslAuthenticationRecords; |
516 | 0 | saslAuthenticationRecords.pushBack(new Asn1OctetStringRecord(saslAuthentication.mechanism)); |
517 | 0 | if (!saslAuthentication.credentials.empty()) |
518 | 0 | { |
519 | 0 | auto credentialsRecord = new Asn1OctetStringRecord(saslAuthentication.credentials.data(), |
520 | 0 | saslAuthentication.credentials.size()); |
521 | 0 | saslAuthenticationRecords.pushBack(credentialsRecord); |
522 | 0 | } |
523 | |
|
524 | 0 | saslAuthenticationRecord = std::make_unique<Asn1ConstructedRecord>( |
525 | 0 | Asn1TagClass::ContextSpecific, static_cast<uint8_t>(LdapBindRequestLayer::AuthenticationType::Sasl), |
526 | 0 | saslAuthenticationRecords); |
527 | 0 | messageRecords.push_back(saslAuthenticationRecord.get()); |
528 | 0 | } |
529 | |
|
530 | 0 | LdapLayer::init(messageId, LdapOperationType::BindRequest, messageRecords, controls); |
531 | 0 | } |
532 | | |
533 | | uint32_t LdapBindRequestLayer::getVersion() const |
534 | 0 | { |
535 | 0 | return getLdapOperationAsn1Record() |
536 | 0 | ->getSubRecords() |
537 | 0 | .at(versionIndex) |
538 | 0 | ->castAs<Asn1IntegerRecord>() |
539 | 0 | ->getIntValue<uint32_t>(); |
540 | 0 | } |
541 | | |
542 | | std::string LdapBindRequestLayer::getName() const |
543 | 0 | { |
544 | 0 | return getLdapOperationAsn1Record()->getSubRecords().at(nameIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
545 | 0 | } |
546 | | |
547 | | LdapBindRequestLayer::AuthenticationType LdapBindRequestLayer::getAuthenticationType() const |
548 | 1.39k | { |
549 | 1.39k | if (getLdapOperationAsn1Record()->getSubRecords().size() <= credentialIndex) |
550 | 24 | { |
551 | 24 | return LdapBindRequestLayer::AuthenticationType::NotApplicable; |
552 | 24 | } |
553 | | |
554 | 1.37k | auto authType = getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->getTagType(); |
555 | 1.37k | switch (authType) |
556 | 1.37k | { |
557 | 1.19k | case 0: |
558 | 1.19k | return LdapBindRequestLayer::AuthenticationType::Simple; |
559 | 160 | case 3: |
560 | 160 | return LdapBindRequestLayer::AuthenticationType::Sasl; |
561 | 16 | default: |
562 | 16 | return LdapBindRequestLayer::AuthenticationType::NotApplicable; |
563 | 1.37k | } |
564 | 1.37k | } |
565 | | |
566 | | std::string LdapBindRequestLayer::getSimpleAuthentication() const |
567 | 0 | { |
568 | 0 | if (getAuthenticationType() != LdapBindRequestLayer::AuthenticationType::Simple) |
569 | 0 | { |
570 | 0 | throw std::invalid_argument("Authentication type is not simple"); |
571 | 0 | } |
572 | | |
573 | 0 | auto authRecord = |
574 | 0 | getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs<Asn1GenericRecord>(); |
575 | 0 | return { reinterpret_cast<const char*>(authRecord->getValue()), authRecord->getValueLength() }; |
576 | 0 | } |
577 | | |
578 | | LdapBindRequestLayer::SaslAuthentication LdapBindRequestLayer::getSaslAuthentication() const |
579 | 0 | { |
580 | 0 | if (getAuthenticationType() != LdapBindRequestLayer::AuthenticationType::Sasl) |
581 | 0 | { |
582 | 0 | throw std::invalid_argument("Authentication type is not sasl"); |
583 | 0 | } |
584 | | |
585 | 0 | auto authRecord = |
586 | 0 | getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs<Asn1ConstructedRecord>(); |
587 | 0 | std::string mechanism; |
588 | 0 | std::vector<uint8_t> credentials; |
589 | 0 | if (authRecord->getSubRecords().size() > saslMechanismIndex) |
590 | 0 | { |
591 | 0 | mechanism = authRecord->getSubRecords().at(saslMechanismIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
592 | 0 | } |
593 | 0 | if (authRecord->getSubRecords().size() > saslCredentialsIndex) |
594 | 0 | { |
595 | 0 | auto credentialsAsString = |
596 | 0 | authRecord->getSubRecords().at(saslCredentialsIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
597 | 0 | credentials.resize(credentialsAsString.size() / 2); |
598 | 0 | hexStringToByteArray(credentialsAsString, credentials.data(), credentials.size()); |
599 | 0 | } |
600 | |
|
601 | 0 | return { mechanism, credentials }; |
602 | 0 | } |
603 | | |
604 | | std::string LdapBindRequestLayer::getExtendedInfoString() const |
605 | 1.39k | { |
606 | 1.39k | switch (getAuthenticationType()) |
607 | 1.39k | { |
608 | 1.19k | case AuthenticationType::Simple: |
609 | 1.19k | return "simple"; |
610 | 160 | case AuthenticationType::Sasl: |
611 | 160 | return "sasl"; |
612 | 40 | default: |
613 | 40 | return "Unknown"; |
614 | 1.39k | } |
615 | 1.39k | } |
616 | | |
617 | | // endregion |
618 | | |
619 | | // region LdapBindResponseLayer |
620 | | |
621 | | LdapBindResponseLayer::LdapBindResponseLayer(uint16_t messageId, LdapResultCode resultCode, |
622 | | const std::string& matchedDN, const std::string& diagnosticMessage, |
623 | | const std::vector<std::string>& referral, |
624 | | const std::vector<uint8_t>& serverSaslCredentials, |
625 | | const std::vector<LdapControl>& controls) |
626 | 0 | { |
627 | 0 | std::vector<Asn1Record*> additionalRecords; |
628 | 0 | std::unique_ptr<Asn1Record> serverSaslCredentialsRecord; |
629 | 0 | if (!serverSaslCredentials.empty()) |
630 | 0 | { |
631 | 0 | serverSaslCredentialsRecord = |
632 | 0 | std::make_unique<Asn1GenericRecord>(Asn1TagClass::ContextSpecific, false, serverSaslCredentialsTagType, |
633 | 0 | serverSaslCredentials.data(), serverSaslCredentials.size()); |
634 | 0 | additionalRecords.push_back(serverSaslCredentialsRecord.get()); |
635 | 0 | } |
636 | |
|
637 | 0 | LdapResponseLayer::init(messageId, LdapOperationType::BindResponse, resultCode, matchedDN, diagnosticMessage, |
638 | 0 | referral, additionalRecords, controls); |
639 | 0 | } |
640 | | |
641 | | std::vector<uint8_t> LdapBindResponseLayer::getServerSaslCredentials() const |
642 | 0 | { |
643 | 0 | try |
644 | 0 | { |
645 | 0 | auto serverSaslCredentialsRecord = |
646 | 0 | getLdapOperationAsn1Record()->getSubRecords().back()->castAs<Asn1GenericRecord>(); |
647 | 0 | return { serverSaslCredentialsRecord->getValue(), |
648 | 0 | serverSaslCredentialsRecord->getValue() + serverSaslCredentialsRecord->getValueLength() }; |
649 | 0 | } |
650 | 0 | catch (const std::exception&) |
651 | 0 | { |
652 | 0 | return {}; |
653 | 0 | } |
654 | 0 | } |
655 | | |
656 | | // endregion |
657 | | |
658 | | // region LdapUnbindRequestLayer |
659 | | |
660 | | LdapUnbindRequestLayer::LdapUnbindRequestLayer(uint16_t messageId, const std::vector<LdapControl>& controls) |
661 | 0 | { |
662 | 0 | LdapLayer::init(messageId, LdapOperationType::UnbindRequest, {}, controls); |
663 | 0 | } |
664 | | |
665 | | // endregion |
666 | | |
667 | | // region LdapSearchRequestLayer |
668 | | |
669 | | const std::unordered_map<LdapSearchRequestLayer::SearchRequestScope::Value, std::string, |
670 | | EnumClassHash<LdapSearchRequestLayer::SearchRequestScope::Value>> |
671 | | SearchRequestScopeToString{ |
672 | | { LdapSearchRequestLayer::SearchRequestScope::BaseObject, "BaseObject" }, |
673 | | { LdapSearchRequestLayer::SearchRequestScope::SingleLevel, "SingleLevel" }, |
674 | | { LdapSearchRequestLayer::SearchRequestScope::WholeSubtree, "WholeSubtree" }, |
675 | | { LdapSearchRequestLayer::SearchRequestScope::Unknown, "Unknown" } |
676 | | }; |
677 | | |
678 | | const std::unordered_map<LdapSearchRequestLayer::DerefAliases::Value, std::string, |
679 | | EnumClassHash<LdapSearchRequestLayer::DerefAliases::Value>> |
680 | | DerefAliasesToString{ |
681 | | { LdapSearchRequestLayer::DerefAliases::NeverDerefAliases, "NeverDerefAliases" }, |
682 | | { LdapSearchRequestLayer::DerefAliases::DerefInSearching, "DerefInSearching" }, |
683 | | { LdapSearchRequestLayer::DerefAliases::DerefFindingBaseObj, "DerefFindingBaseObj" }, |
684 | | { LdapSearchRequestLayer::DerefAliases::DerefAlways, "DerefAlways" }, |
685 | | { LdapSearchRequestLayer::DerefAliases::Unknown, "Unknown" } |
686 | | }; |
687 | | |
688 | | std::string LdapSearchRequestLayer::SearchRequestScope::toString() const |
689 | 1.06k | { |
690 | 1.06k | return SearchRequestScopeToString.at(m_Value); |
691 | 1.06k | } |
692 | | |
693 | | LdapSearchRequestLayer::SearchRequestScope LdapSearchRequestLayer::SearchRequestScope::fromUintValue(uint8_t value) |
694 | 1.06k | { |
695 | 1.06k | if (value <= 2) |
696 | 982 | { |
697 | 982 | return static_cast<LdapSearchRequestLayer::SearchRequestScope::Value>(value); |
698 | 982 | } |
699 | | |
700 | 82 | return LdapSearchRequestLayer::SearchRequestScope::Unknown; |
701 | 1.06k | } |
702 | | |
703 | | std::string LdapSearchRequestLayer::DerefAliases::toString() const |
704 | 0 | { |
705 | 0 | return DerefAliasesToString.at(m_Value); |
706 | 0 | } |
707 | | |
708 | | LdapSearchRequestLayer::DerefAliases LdapSearchRequestLayer::DerefAliases::fromUintValue(uint8_t value) |
709 | 0 | { |
710 | 0 | if (value <= 3) |
711 | 0 | { |
712 | 0 | return static_cast<LdapSearchRequestLayer::DerefAliases::Value>(value); |
713 | 0 | } |
714 | | |
715 | 0 | return LdapSearchRequestLayer::DerefAliases::Unknown; |
716 | 0 | } |
717 | | |
718 | | LdapSearchRequestLayer::LdapSearchRequestLayer(uint16_t messageId, const std::string& baseObject, |
719 | | SearchRequestScope scope, DerefAliases derefAliases, |
720 | | uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, |
721 | | Asn1Record* filterRecord, const std::vector<std::string>& attributes, |
722 | | const std::vector<LdapControl>& controls) |
723 | 0 | { |
724 | 0 | Asn1OctetStringRecord baseObjectRecord(baseObject); |
725 | 0 | Asn1EnumeratedRecord scopeRecord(scope); |
726 | 0 | Asn1EnumeratedRecord derefAliasesRecord(derefAliases); |
727 | 0 | Asn1IntegerRecord sizeLimitRecord(sizeLimit); |
728 | 0 | Asn1IntegerRecord timeLimitRecord(timeLimit); |
729 | 0 | Asn1BooleanRecord typeOnlyRecord(typesOnly); |
730 | |
|
731 | 0 | PointerVector<Asn1Record> attributeSubRecords; |
732 | 0 | for (const auto& attribute : attributes) |
733 | 0 | { |
734 | 0 | attributeSubRecords.pushBack(new Asn1OctetStringRecord(attribute)); |
735 | 0 | } |
736 | 0 | Asn1SequenceRecord attributesRecord(attributeSubRecords); |
737 | |
|
738 | 0 | LdapLayer::init(messageId, LdapOperationType::SearchRequest, |
739 | 0 | { &baseObjectRecord, &scopeRecord, &derefAliasesRecord, &sizeLimitRecord, &timeLimitRecord, |
740 | 0 | &typeOnlyRecord, filterRecord, &attributesRecord }, |
741 | 0 | controls); |
742 | 0 | } |
743 | | |
744 | | std::string LdapSearchRequestLayer::getBaseObject() const |
745 | 1.06k | { |
746 | 1.06k | return getLdapOperationAsn1Record() |
747 | 1.06k | ->getSubRecords() |
748 | 1.06k | .at(baseObjectIndex) |
749 | 1.06k | ->castAs<Asn1OctetStringRecord>() |
750 | 1.06k | ->getValue(); |
751 | 1.06k | } |
752 | | |
753 | | LdapSearchRequestLayer::SearchRequestScope LdapSearchRequestLayer::getScope() const |
754 | 1.06k | { |
755 | 1.06k | return LdapSearchRequestLayer::SearchRequestScope::fromUintValue(getLdapOperationAsn1Record() |
756 | 1.06k | ->getSubRecords() |
757 | 1.06k | .at(scopeIndex) |
758 | 1.06k | ->castAs<Asn1EnumeratedRecord>() |
759 | 1.06k | ->getIntValue<uint8_t>()); |
760 | 1.06k | } |
761 | | |
762 | | LdapSearchRequestLayer::DerefAliases LdapSearchRequestLayer::getDerefAlias() const |
763 | 0 | { |
764 | 0 | return LdapSearchRequestLayer::DerefAliases::fromUintValue(getLdapOperationAsn1Record() |
765 | 0 | ->getSubRecords() |
766 | 0 | .at(derefAliasIndex) |
767 | 0 | ->castAs<Asn1EnumeratedRecord>() |
768 | 0 | ->getIntValue<uint8_t>()); |
769 | 0 | } |
770 | | |
771 | | uint8_t LdapSearchRequestLayer::getSizeLimit() const |
772 | 0 | { |
773 | 0 | return getLdapOperationAsn1Record() |
774 | 0 | ->getSubRecords() |
775 | 0 | .at(sizeLimitIndex) |
776 | 0 | ->castAs<Asn1IntegerRecord>() |
777 | 0 | ->getIntValue<uint8_t>(); |
778 | 0 | } |
779 | | |
780 | | uint8_t LdapSearchRequestLayer::getTimeLimit() const |
781 | 0 | { |
782 | 0 | return getLdapOperationAsn1Record() |
783 | 0 | ->getSubRecords() |
784 | 0 | .at(timeLimitIndex) |
785 | 0 | ->castAs<Asn1IntegerRecord>() |
786 | 0 | ->getIntValue<uint8_t>(); |
787 | 0 | } |
788 | | |
789 | | bool LdapSearchRequestLayer::getTypesOnly() const |
790 | 0 | { |
791 | 0 | return getLdapOperationAsn1Record() |
792 | 0 | ->getSubRecords() |
793 | 0 | .at(typesOnlyIndex) |
794 | 0 | ->castAs<Asn1BooleanRecord>() |
795 | 0 | ->getValue(); |
796 | 0 | } |
797 | | |
798 | | Asn1Record* LdapSearchRequestLayer::getFilter() const |
799 | 0 | { |
800 | 0 | return getLdapOperationAsn1Record()->getSubRecords().at(filterIndex); |
801 | 0 | } |
802 | | |
803 | | std::vector<std::string> LdapSearchRequestLayer::getAttributes() const |
804 | 0 | { |
805 | 0 | std::vector<std::string> result; |
806 | 0 | if (getLdapOperationAsn1Record()->getSubRecords().size() <= attributesIndex) |
807 | 0 | { |
808 | 0 | return result; |
809 | 0 | } |
810 | | |
811 | 0 | auto attributesRecord = |
812 | 0 | getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs<Asn1SequenceRecord>(); |
813 | 0 | for (auto attribute : attributesRecord->getSubRecords()) |
814 | 0 | { |
815 | 0 | result.push_back(attribute->castAs<Asn1OctetStringRecord>()->getValue()); |
816 | 0 | } |
817 | |
|
818 | 0 | return result; |
819 | 0 | } |
820 | | |
821 | | std::string LdapSearchRequestLayer::getExtendedInfoString() const |
822 | 1.06k | { |
823 | 1.06k | auto baseObject = getBaseObject(); |
824 | 1.06k | if (baseObject.empty()) |
825 | 0 | { |
826 | 0 | baseObject = "ROOT"; |
827 | 0 | } |
828 | | |
829 | 1.06k | return "\"" + baseObject + "\", " + getScope().toString(); |
830 | 1.06k | } |
831 | | |
832 | | // endregion |
833 | | |
834 | | // region LdapSearchResultEntryLayer |
835 | | |
836 | | LdapSearchResultEntryLayer::LdapSearchResultEntryLayer(uint16_t messageId, const std::string& objectName, |
837 | | const std::vector<LdapAttribute>& attributes, |
838 | | const std::vector<LdapControl>& controls) |
839 | 0 | { |
840 | 0 | PointerVector<Asn1Record> attributesSubRecords; |
841 | 0 | for (const auto& attribute : attributes) |
842 | 0 | { |
843 | 0 | PointerVector<Asn1Record> valuesSubRecords; |
844 | 0 | for (const auto& value : attribute.values) |
845 | 0 | { |
846 | 0 | valuesSubRecords.pushBack(new Asn1OctetStringRecord(value)); |
847 | 0 | } |
848 | |
|
849 | 0 | Asn1OctetStringRecord typeRecord(attribute.type); |
850 | 0 | Asn1SetRecord valuesRecord(valuesSubRecords); |
851 | |
|
852 | 0 | attributesSubRecords.pushBack(new Asn1SequenceRecord({ &typeRecord, &valuesRecord })); |
853 | 0 | } |
854 | |
|
855 | 0 | Asn1OctetStringRecord objectNameRecord(objectName); |
856 | 0 | Asn1SequenceRecord attributesRecord(attributesSubRecords); |
857 | |
|
858 | 0 | LdapLayer::init(messageId, LdapOperationType::SearchResultEntry, { &objectNameRecord, &attributesRecord }, |
859 | 0 | controls); |
860 | 0 | } |
861 | | |
862 | | std::string LdapSearchResultEntryLayer::getObjectName() const |
863 | 0 | { |
864 | 0 | return getLdapOperationAsn1Record() |
865 | 0 | ->getSubRecords() |
866 | 0 | .at(objectNameIndex) |
867 | 0 | ->castAs<Asn1OctetStringRecord>() |
868 | 0 | ->getValue(); |
869 | 0 | } |
870 | | |
871 | | std::vector<LdapAttribute> LdapSearchResultEntryLayer::getAttributes() const |
872 | 0 | { |
873 | 0 | std::vector<LdapAttribute> result; |
874 | |
|
875 | 0 | auto attributes = |
876 | 0 | getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs<Asn1SequenceRecord>(); |
877 | 0 | for (auto attributeRecord : attributes->getSubRecords()) |
878 | 0 | { |
879 | 0 | auto attrAsSequence = attributeRecord->castAs<Asn1SequenceRecord>(); |
880 | |
|
881 | 0 | auto type = |
882 | 0 | attrAsSequence->getSubRecords().at(attributeTypeIndex)->castAs<Asn1OctetStringRecord>()->getValue(); |
883 | |
|
884 | 0 | std::vector<std::string> values; |
885 | 0 | auto valuesRecord = attrAsSequence->getSubRecords().at(attributeValueIndex)->castAs<Asn1SetRecord>(); |
886 | |
|
887 | 0 | for (auto valueRecord : valuesRecord->getSubRecords()) |
888 | 0 | { |
889 | 0 | values.push_back(valueRecord->castAs<Asn1OctetStringRecord>()->getValue()); |
890 | 0 | } |
891 | |
|
892 | 0 | LdapAttribute ldapAttribute = { type, values }; |
893 | 0 | result.push_back(ldapAttribute); |
894 | 0 | } |
895 | |
|
896 | 0 | return result; |
897 | 0 | } |
898 | | |
899 | | // endregion |
900 | | } // namespace pcpp |