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