/src/PcapPlusPlus/Packet++/header/LdapLayer.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "Layer.h" |
4 | | #include "Asn1Codec.h" |
5 | | #include <ostream> |
6 | | #include <string> |
7 | | #include <functional> |
8 | | |
9 | | /// @file |
10 | | |
11 | | /// @namespace pcpp |
12 | | /// @brief The main namespace for the PcapPlusPlus lib |
13 | | namespace pcpp |
14 | | { |
15 | | /// @class LdapOperationType |
16 | | /// @brief An enum wrapper class for LDAP operation types |
17 | | class LdapOperationType |
18 | | { |
19 | | public: |
20 | | /// Define enum types and the corresponding int values |
21 | | enum Value : uint8_t |
22 | | { |
23 | | /// Bind Request |
24 | | BindRequest = 0, |
25 | | /// Bind Response |
26 | | BindResponse = 1, |
27 | | /// Unbind Request |
28 | | UnbindRequest = 2, |
29 | | /// Search Request |
30 | | SearchRequest = 3, |
31 | | /// Search Result Entry |
32 | | SearchResultEntry = 4, |
33 | | /// Search Result Done |
34 | | SearchResultDone = 5, |
35 | | /// Modify Request |
36 | | ModifyRequest = 6, |
37 | | /// Modify Response |
38 | | ModifyResponse = 7, |
39 | | /// Add Request |
40 | | AddRequest = 8, |
41 | | /// Add Response |
42 | | AddResponse = 9, |
43 | | /// Delete Request |
44 | | DeleteRequest = 10, |
45 | | /// Delete Response |
46 | | DeleteResponse = 11, |
47 | | /// Modify DN (Distinguished Name) Request |
48 | | ModifyDNRequest = 12, |
49 | | /// Modify DN (Distinguished Name) Response |
50 | | ModifyDNResponse = 13, |
51 | | /// Compare Request |
52 | | CompareRequest = 14, |
53 | | /// Compare Response |
54 | | CompareResponse = 15, |
55 | | /// Abandon Request |
56 | | AbandonRequest = 16, |
57 | | /// Search Result Reference |
58 | | SearchResultReference = 19, |
59 | | /// Extended Request |
60 | | ExtendedRequest = 23, |
61 | | /// Extended Response |
62 | | ExtendedResponse = 24, |
63 | | /// Intermediate Response |
64 | | IntermediateResponse = 25, |
65 | | /// Unknown operation type |
66 | | Unknown = 255 |
67 | | }; |
68 | | |
69 | | LdapOperationType() = default; |
70 | | |
71 | | // cppcheck-suppress noExplicitConstructor |
72 | | /// Construct LdapOperationType from Value enum |
73 | | /// @param[in] value the operation type enum value |
74 | 956 | constexpr LdapOperationType(Value value) : m_Value(value) |
75 | 956 | {} |
76 | | |
77 | | /// @return A string representation of the operation type |
78 | | std::string toString() const; |
79 | | |
80 | | /// A static method that creates LdapOperationType from an integer value |
81 | | /// @param[in] value The operation type integer value |
82 | | /// @return The operation type that corresponds to the integer value. If the integer value |
83 | | /// doesn't corresponds to any operation type, LdapOperationType::Unknown is returned |
84 | | static LdapOperationType fromUintValue(uint8_t value); |
85 | | |
86 | | // Allow switch and comparisons. |
87 | | constexpr operator Value() const |
88 | 20.6k | { |
89 | 20.6k | return m_Value; |
90 | 20.6k | } |
91 | | |
92 | | // Prevent usage: if(LdapOperationType) |
93 | | explicit operator bool() const = delete; |
94 | | |
95 | | private: |
96 | | Value m_Value = LdapOperationType::Unknown; |
97 | | }; |
98 | | |
99 | | /// @class LdapResultCode |
100 | | /// @brief An enum wrapper class for LDAP result codes |
101 | | class LdapResultCode |
102 | | { |
103 | | public: |
104 | | /// Define enum types and the corresponding int values |
105 | | enum Value : uint8_t |
106 | | { |
107 | | /// Indicates that the associated operation completed successfully |
108 | | Success = 0, |
109 | | /// Indicates that there was a problem with the client’s use of the LDAP protocol |
110 | | OperationsError = 1, |
111 | | /// Indicates that there was a problem with the client’s use of the LDAP protocol |
112 | | ProtocolError = 2, |
113 | | /// Indicates that the associated operation failed because it hadn’t completed by the time |
114 | | /// a maximum processing time limit had been reached |
115 | | TimeLimitExceeded = 3, |
116 | | /// Indicates that the associated search operation failed because the server has determined |
117 | | /// that the number of entries that would be returned in response to the search would exceed |
118 | | /// the upper bound for that operation |
119 | | SizeLimitExceeded = 4, |
120 | | /// Indicates that the associated compare request targeted an entry that exists and that contains |
121 | | /// the targeted attribute, but does not have any value that matches the provided assertion value |
122 | | CompareFalse = 5, |
123 | | /// Indicates that the associated compare request targeted an entry that exists and that contains |
124 | | /// the targeted attribute with a value that matches the provided assertion value |
125 | | CompareTrue = 6, |
126 | | /// Indicates that the associated bind operation failed because the client attempted to authenticate |
127 | | /// with a mechanism that the server does not support or that it does not allow the client to use |
128 | | AuthMethodNotSupported = 7, |
129 | | /// Indicates that the server requires the client to authenticate with a stronger form of authentication |
130 | | StrongerAuthRequired = 8, |
131 | | /// Indicates that the request cannot be processed exactly as issued, but that it might succeed |
132 | | /// if re-issued to a different server, or is updated to target a different location in the DIT |
133 | | Referral = 10, |
134 | | /// Indicates that some administrative limit within the server was exceeded while processing the request |
135 | | AdminLimitExceeded = 11, |
136 | | /// Indicates that the request includes a control with a criticality of true, |
137 | | /// but that control could not be honored for some reason |
138 | | UnavailableCriticalExtension = 12, |
139 | | /// Indicates that the server is only willing to process the requested operation if it is received |
140 | | /// over a secure connection that does not allow an eavesdropper to decipher or alter the contents |
141 | | /// of the request or response |
142 | | ConfidentialityRequired = 13, |
143 | | /// Indicates that the server has completed a portion of the processing for the provided SASL |
144 | | /// bind request, but that it needs additional information from the client to complete the authentication |
145 | | SaslBindInProgress = 14, |
146 | | /// Indicates that the request targeted an attribute that does not exist in the specified entry |
147 | | NoSuchAttribute = 16, |
148 | | /// Indicates that the request attempted to provide one or more values for an attribute type |
149 | | /// that is not defined in the server schema |
150 | | UndefinedAttributeType = 17, |
151 | | /// Indicates that the search request tried to perform some type of matching that is not |
152 | | /// supported for the target attribute type |
153 | | InappropriateMatching = 18, |
154 | | /// Indicates that the requested operation would have resulted in an entry that violates |
155 | | /// some constraint defined within the server |
156 | | ConstraintViolation = 19, |
157 | | /// Indicates that the requested operation would have resulted in an attribute in which |
158 | | /// the same value appeared more than once |
159 | | AttributeOrValueExists = 20, |
160 | | /// Indicates that the requested add or modify operation would have resulted in an entry |
161 | | /// that had at least one attribute value that does not conform to the constraints of the |
162 | | /// associated attribute syntax |
163 | | InvalidAttributeSyntax = 21, |
164 | | /// Indicates that the requested operation targeted an entry that does not exist within the DIT |
165 | | NoSuchObject = 32, |
166 | | /// Indicates that a problem occurred while attempting to dereference an alias during search processing |
167 | | AliasProblem = 33, |
168 | | /// Indicates that the request included a malformed entry DN |
169 | | InvalidDNSyntax = 34, |
170 | | /// Indicates that the server encountered an alias while processing the request and that there |
171 | | /// was some problem related to that alias |
172 | | AliasDereferencingProblem = 36, |
173 | | /// Indicates that the client attempted to bind in an inappropriate manner that is inappropriate |
174 | | /// for the target account |
175 | | InappropriateAuthentication = 48, |
176 | | /// Indicates that the client attempted to bind with a set of credentials that cannot |
177 | | /// be used to authenticate |
178 | | InvalidCredentials = 49, |
179 | | /// Indicates that the client requested an operation for which it does not have the necessary |
180 | | /// access control permissions |
181 | | InsufficientAccessRights = 50, |
182 | | /// Indicates that the requested operation cannot be processed because the server is currently too busy |
183 | | Busy = 51, |
184 | | /// Indicates that the server is currently not available to process the requested operation |
185 | | Unavailable = 52, |
186 | | /// Indicates that the server is not willing to process the requested operation for some reason |
187 | | UnwillingToPerform = 53, |
188 | | /// Indicates that the server detected some kind of circular reference in the course |
189 | | /// of processing an operation |
190 | | LoopDetect = 54, |
191 | | /// Indicates that the requested add or modify DN operation would have resulted in an entry |
192 | | /// that violates some naming constraint within the server |
193 | | NamingViolation = 64, |
194 | | /// Indicates that the requested operation would have resulted in an entry that has |
195 | | /// an inappropriate set of object classes, or whose attributes violate the constraints |
196 | | /// associated with its set of object classes |
197 | | ObjectClassViolation = 65, |
198 | | /// Indicates that the requested operation is only supported for leaf entries, |
199 | | /// but the targeted entry has one or more subordinates |
200 | | NotAllowedOnNonLeaf = 66, |
201 | | /// Indicates that the requested modify operation would have resulted in an entry that |
202 | | /// does not include all of the attributes used in its RDN |
203 | | NotAllowedOnRDN = 67, |
204 | | /// Indicates that the requested operation would have resulted in an entry with the same |
205 | | /// DN as an entry that already exists in the server |
206 | | EntryAlreadyExists = 68, |
207 | | /// Indicates that the requested modify operation would have altered the target entry’s |
208 | | /// set of object classes in a way that is not supported |
209 | | ObjectClassModsProhibited = 69, |
210 | | /// Indicates that the requested operation would have required manipulating information |
211 | | /// in multiple servers in a way that is not supported |
212 | | AffectsMultipleDSAs = 71, |
213 | | /// Used when a problem occurs for which none of the other result codes is more appropriate |
214 | | Other = 80, |
215 | | /// Unknown result code |
216 | | Unknown = 255 |
217 | | }; |
218 | | |
219 | | LdapResultCode() = default; |
220 | | |
221 | | // cppcheck-suppress noExplicitConstructor |
222 | | /// Construct LdapResultCode from Value enum |
223 | | /// @param[in] value the result code enum value |
224 | 0 | constexpr LdapResultCode(Value value) : m_Value(value) |
225 | 0 | {} |
226 | | |
227 | | /// @return A string representation of the result code |
228 | | std::string toString() const; |
229 | | |
230 | | /// A static method that creates LdapResultCode from an integer value |
231 | | /// @param[in] value The result code integer value |
232 | | /// @return The result code that corresponds to the integer value. If the integer value |
233 | | /// doesn't corresponds to any operation type, LdapResultCode::Unknown is returned |
234 | | static LdapResultCode fromUintValue(uint8_t value); |
235 | | |
236 | | // Allow switch and comparisons |
237 | | constexpr operator Value() const |
238 | 0 | { |
239 | 0 | return m_Value; |
240 | 0 | } |
241 | | |
242 | | // Prevent usage: if(LdapResultCode) |
243 | | explicit operator bool() const = delete; |
244 | | |
245 | | private: |
246 | | Value m_Value = LdapResultCode::Unknown; |
247 | | }; |
248 | | |
249 | | /// @struct LdapControl |
250 | | /// A struct that represents an LDAP Control |
251 | | struct LdapControl |
252 | | { |
253 | | /// LDAP control type |
254 | | std::string controlType; |
255 | | /// LDAP control value |
256 | | std::string controlValue; |
257 | | |
258 | | /// Equality operator overload for this struct |
259 | | /// @param[in] other The value to compare with |
260 | | /// @return True if both values are equal, false otherwise |
261 | | bool operator==(const LdapControl& other) const |
262 | 0 | { |
263 | 0 | return controlType == other.controlType && controlValue == other.controlValue; |
264 | 0 | } |
265 | | }; |
266 | | |
267 | | /// @struct LdapAttribute |
268 | | /// A struct that represents an LDAP attribute |
269 | | struct LdapAttribute |
270 | | { |
271 | | /// Attribute description |
272 | | std::string type; |
273 | | /// A list of attribute values (zero or more) |
274 | | std::vector<std::string> values; |
275 | | |
276 | | /// Equality operator overload for this struct |
277 | | /// @param[in] other The value to compare with |
278 | | /// @return True if both values are equal, false otherwise |
279 | | bool operator==(const LdapAttribute& other) const |
280 | 0 | { |
281 | 0 | return type == other.type && values == other.values; |
282 | 0 | } |
283 | | }; |
284 | | |
285 | | /// @class LdapLayer |
286 | | /// Represents an LDAP message |
287 | | class LdapLayer : public Layer |
288 | | { |
289 | | public: |
290 | | /// A constructor to create a new LDAP message |
291 | | /// @param[in] messageId The LDAP message ID |
292 | | /// @param[in] operationType The LDAP operation type |
293 | | /// @param[in] messageRecords A vector of ASN.1 records that comprise the LDAP message |
294 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
295 | | /// will be created without LDAP controls |
296 | | LdapLayer(uint16_t messageId, LdapOperationType operationType, const std::vector<Asn1Record*>& messageRecords, |
297 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
298 | | |
299 | 20.3k | ~LdapLayer() override = default; |
300 | | |
301 | | /// @return The root ASN.1 record of the LDAP message. All of the message data will be under this record. |
302 | | /// If the Root ASN.1 record is malformed, an exception is thrown |
303 | | Asn1SequenceRecord* getRootAsn1Record() const; |
304 | | |
305 | | /// @return The ASN.1 record of the specific LDAP operation in this LDAP message. Each operation has a specific |
306 | | /// structure. If the Operation ASN.1 record is malformed, an exception is thrown |
307 | | Asn1ConstructedRecord* getLdapOperationAsn1Record() const; |
308 | | |
309 | | /// @return The LDAP message ID. If the ASN.1 record is malformed, an exception is thrown |
310 | | uint16_t getMessageID() const; |
311 | | |
312 | | /// @return A vector of LDAP controls in this message. If the message contains no controls then an empty |
313 | | /// vector is returned. If the Controls ASN.1 record is malformed, an exception is thrown |
314 | | std::vector<LdapControl> getControls() const; |
315 | | |
316 | | /// @return The LDAP operation of this message. If the Operation ASN.1 record is malformed, an exception is |
317 | | /// thrown |
318 | | virtual LdapOperationType getLdapOperationType() const; |
319 | | |
320 | | /// Most getter methods in this class throw an exception if the corresponding ASN.1 record is invalid. |
321 | | /// This is a wrapper method that allows calling these getters without adding a `try...catch` clause. |
322 | | /// It accepts the getter method and an out variable. It tries to call the getter and if no exception |
323 | | /// is thrown, the out variable will contain the result. |
324 | | /// |
325 | | /// Here is an example: |
326 | | /// @code |
327 | | /// uint16_t messageId; |
328 | | /// ldapLayer->tryGet(&pcpp::LdapLayer::getMessageID, messageId)); |
329 | | /// @endcode |
330 | | /// |
331 | | /// We call getMessageID(), if no exception is thrown the variable messageId will hold the result |
332 | | /// |
333 | | /// @tparam Method The class method type |
334 | | /// @tparam ResultType The expected result type (for example: uint8_t, std::string, etc.) |
335 | | /// @param[in] method The class method to call |
336 | | /// @param[out] result An outvariable to contain the result if no exception is thrown |
337 | | /// @return True if no exception was thrown or false otherwise |
338 | | template <typename Method, typename ResultType> bool tryGet(Method method, ResultType& result) |
339 | | { |
340 | | return internalTryGet(this, method, result); |
341 | | } |
342 | | |
343 | | /// A static method that checks whether a source or dest port match those associated with the LDAP protocol |
344 | | /// @param[in] port The port number to check |
345 | | /// @return True if this is an LDAP port, false otherwise |
346 | | static bool isLdapPort(uint16_t port) |
347 | 95.2k | { |
348 | 95.2k | return port == 389; |
349 | 95.2k | } |
350 | | |
351 | | /// A static message to parse an LDAP message from raw data |
352 | | /// @param[in] data A pointer to the raw data |
353 | | /// @param[in] dataLen Size of the data in bytes |
354 | | /// @param[in] prevLayer A pointer to the previous layer |
355 | | /// @param[in] packet A pointer to the Packet instance where layer will be stored in |
356 | | /// @return An instance of LdapLayer if this is indeed an LDAP message, nullptr otherwise |
357 | | static LdapLayer* parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
358 | | |
359 | | // implement abstract methods |
360 | | |
361 | | /// Tries to identify more LDAP messages in this packet if exist |
362 | | void parseNextLayer() override; |
363 | | |
364 | | /// @return The size of the LDAP message |
365 | | size_t getHeaderLen() const override |
366 | 23.8k | { |
367 | 23.8k | return m_Asn1Record->getTotalLength(); |
368 | 23.8k | } |
369 | | |
370 | | void computeCalculateFields() override |
371 | 3.46k | {} |
372 | | |
373 | | OsiModelLayer getOsiModelLayer() const override |
374 | 3.46k | { |
375 | 3.46k | return OsiModelApplicationLayer; |
376 | 3.46k | } |
377 | | |
378 | | std::string toString() const override; |
379 | | |
380 | | protected: |
381 | | std::unique_ptr<Asn1Record> m_Asn1Record; |
382 | | |
383 | | LdapLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
384 | | Packet* packet); |
385 | 0 | LdapLayer() = default; |
386 | | void init(uint16_t messageId, LdapOperationType operationType, const std::vector<Asn1Record*>& messageRecords, |
387 | | const std::vector<LdapControl>& controls); |
388 | | virtual std::string getExtendedInfoString() const |
389 | 3.06k | { |
390 | 3.06k | return ""; |
391 | 3.06k | } |
392 | | |
393 | | static constexpr int messageIdIndex = 0; |
394 | | static constexpr int operationTypeIndex = 1; |
395 | | static constexpr int controlsIndex = 2; |
396 | | |
397 | | static constexpr int controlTypeIndex = 0; |
398 | | static constexpr int controlValueIndex = 1; |
399 | | |
400 | | template <typename LdapClass, typename Method, typename ResultType> |
401 | | bool internalTryGet(LdapClass* thisPtr, Method method, ResultType& result) |
402 | | { |
403 | | try |
404 | | { |
405 | | result = std::mem_fn(method)(thisPtr); |
406 | | return true; |
407 | | } |
408 | | catch (...) |
409 | | { |
410 | | return false; |
411 | | } |
412 | | } |
413 | | }; |
414 | | |
415 | | /// @class LdapResponseLayer |
416 | | /// An abstract class for representing an LDAP response message. It's the parent class |
417 | | /// for all response message layers |
418 | | class LdapResponseLayer : public LdapLayer |
419 | | { |
420 | | public: |
421 | | /// @return LDAP result code |
422 | | LdapResultCode getResultCode() const; |
423 | | |
424 | | /// @return An optional distinguished name (DN) that may be included in the response to a request |
425 | | /// targeting an entry that does not exist |
426 | | std::string getMatchedDN() const; |
427 | | |
428 | | /// @return An optional string that can provide additional information about the processing that |
429 | | /// was performed |
430 | | std::string getDiagnosticMessage() const; |
431 | | |
432 | | /// @return An optional list of one or more URIs that the client may use to re-try the operation |
433 | | /// somewhere else. If referral doesn't exist on the message, and empty vector is returned |
434 | | std::vector<std::string> getReferral() const; |
435 | | |
436 | | protected: |
437 | | static constexpr int resultCodeIndex = 0; |
438 | | static constexpr int matchedDNIndex = 1; |
439 | | static constexpr int diagnotsticsMessageIndex = 2; |
440 | | static constexpr int referralIndex = 3; |
441 | | |
442 | | static constexpr uint8_t referralTagType = 3; |
443 | | |
444 | 0 | LdapResponseLayer() = default; |
445 | | LdapResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
446 | | Packet* packet) |
447 | 6.49k | : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
448 | 6.49k | {} |
449 | | |
450 | | LdapResponseLayer(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, |
451 | | const std::string& matchedDN, const std::string& diagnosticMessage, |
452 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
453 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
454 | | |
455 | | void init(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, |
456 | | const std::string& matchedDN, const std::string& diagnosticMessage, |
457 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
458 | | const std::vector<Asn1Record*>& additionalRecords = std::vector<Asn1Record*>(), |
459 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
460 | | |
461 | | std::string getExtendedInfoString() const override; |
462 | | }; |
463 | | |
464 | | /// @class LdapBindRequestLayer |
465 | | /// Represents LDAP bind request operation |
466 | | class LdapBindRequestLayer : public LdapLayer |
467 | | { |
468 | | public: |
469 | | /// An enum to represent the bind request authentication type |
470 | | enum class AuthenticationType : uint8_t |
471 | | { |
472 | | /// Simple authentication |
473 | | Simple = 0, |
474 | | /// SASL authentication |
475 | | Sasl = 3, |
476 | | /// Unknown / not application authentication type |
477 | | NotApplicable = 255 |
478 | | }; |
479 | | |
480 | | /// @struct SaslAuthentication |
481 | | /// A struct to represent SASL authentication |
482 | | struct SaslAuthentication |
483 | | { |
484 | | /// The SASL mechanism |
485 | | std::string mechanism; |
486 | | /// Encoded SASL credentials |
487 | | std::vector<uint8_t> credentials; |
488 | | |
489 | | /// Equality operator overload for this struct |
490 | | /// @param[in] other The value to compare with |
491 | | /// @return True if both values are equal, false otherwise |
492 | | bool operator==(const SaslAuthentication& other) const |
493 | 0 | { |
494 | 0 | return mechanism == other.mechanism && credentials == other.credentials; |
495 | 0 | } |
496 | | |
497 | | /// Inequality operator overload for this struct |
498 | | /// @param[in] other The value to compare with |
499 | | /// @return False if both values are equal, true otherwise |
500 | | bool operator!=(const SaslAuthentication& other) const |
501 | 0 | { |
502 | 0 | return !operator==(other); |
503 | 0 | } |
504 | | }; |
505 | | |
506 | | /// A constructor to create a new LDAP bind request message with simple authentication |
507 | | /// @param[in] messageId The LDAP message ID |
508 | | /// @param[in] version The LDAP protocol version that the client wants to use |
509 | | /// @param[in] name The DN of the user to authenticate |
510 | | /// @param[in] simpleAuthentication Simple authentication to use in this message |
511 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
512 | | /// will be created without LDAP controls |
513 | | LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, |
514 | | const std::string& simpleAuthentication, |
515 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
516 | | |
517 | | /// A constructor to create a new LDAP bind request message with SASL authentication |
518 | | /// @param[in] messageId The LDAP message ID |
519 | | /// @param[in] version The LDAP protocol version that the client wants to use |
520 | | /// @param[in] name The DN of the user to authenticate |
521 | | /// @param[in] saslAuthentication SASL authentication to use in this message |
522 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
523 | | /// will be created without LDAP controls |
524 | | LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, |
525 | | const SaslAuthentication& saslAuthentication, |
526 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
527 | | |
528 | | /// @return The LDAP protocol version that the client wants to use |
529 | | uint32_t getVersion() const; |
530 | | |
531 | | /// @return The DN of the user to authenticate |
532 | | std::string getName() const; |
533 | | |
534 | | /// @return The authentication type included in this message |
535 | | AuthenticationType getAuthenticationType() const; |
536 | | |
537 | | /// @return The simple authentication included in this message |
538 | | /// @throws std::invalid_argument if the message doesn't include simple authentication |
539 | | std::string getSimpleAuthentication() const; |
540 | | |
541 | | /// @return The SASL authentication included in this message |
542 | | /// @throws std::invalid_argument if the message doesn't include SASL authentication |
543 | | SaslAuthentication getSaslAuthentication() const; |
544 | | |
545 | | template <typename Method, typename ResultType> bool tryGet(Method method, ResultType& result) |
546 | | { |
547 | | return internalTryGet(this, method, result); |
548 | | } |
549 | | |
550 | | protected: |
551 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
552 | | |
553 | | LdapBindRequestLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
554 | | Packet* packet) |
555 | 2.27k | : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
556 | 2.27k | {} |
557 | | |
558 | | std::string getExtendedInfoString() const override; |
559 | | |
560 | | private: |
561 | | static constexpr int versionIndex = 0; |
562 | | static constexpr int nameIndex = 1; |
563 | | static constexpr int credentialIndex = 2; |
564 | | |
565 | | static constexpr int saslMechanismIndex = 0; |
566 | | static constexpr int saslCredentialsIndex = 1; |
567 | | }; |
568 | | |
569 | | /// @class LdapBindResponseLayer |
570 | | /// Represents LDAP bind response operation |
571 | | class LdapBindResponseLayer : public LdapResponseLayer |
572 | | { |
573 | | public: |
574 | | /// A constructor to create a new LDAP bind response message |
575 | | /// @param[in] messageId The LDAP message ID |
576 | | /// @param[in] resultCode The LDAP result code |
577 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
578 | | /// pass an empty string |
579 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
580 | | /// pass an empty string |
581 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
582 | | /// parameter. If not provided then referral won't be added to the message |
583 | | /// @param[in] serverSaslCredentials Encoded server SASL credentials for use in subsequent processing |
584 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
585 | | /// will be created without LDAP controls |
586 | | LdapBindResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
587 | | const std::string& diagnosticMessage, |
588 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
589 | | const std::vector<uint8_t>& serverSaslCredentials = std::vector<uint8_t>(), |
590 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
591 | | |
592 | | /// @return Encoded server SASL credentials for use in subsequent processing |
593 | | std::vector<uint8_t> getServerSaslCredentials() const; |
594 | | |
595 | | protected: |
596 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
597 | | |
598 | | static constexpr int serverSaslCredentialsTagType = 7; |
599 | | |
600 | | LdapBindResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
601 | | Packet* packet) |
602 | 1.18k | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
603 | 1.18k | {} |
604 | | }; |
605 | | |
606 | | /// @class LdapUnbindRequestLayer |
607 | | /// Represents LDAP unbind operation |
608 | | class LdapUnbindRequestLayer : public LdapLayer |
609 | | { |
610 | | public: |
611 | | /// A constructor to create a new LDAP unbind message |
612 | | /// @param[in] messageId The LDAP message ID |
613 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
614 | | /// will be created without LDAP controls |
615 | | explicit LdapUnbindRequestLayer(uint16_t messageId, |
616 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
617 | | |
618 | | // Unbind request has no operation record |
619 | | Asn1ConstructedRecord* getLdapOperationAsn1Record() const = delete; |
620 | | |
621 | | LdapOperationType getLdapOperationType() const override |
622 | 530 | { |
623 | 530 | return LdapOperationType::UnbindRequest; |
624 | 530 | } |
625 | | |
626 | | template <typename Method, typename ResultType> bool tryGet(Method method, ResultType& result) |
627 | | { |
628 | | return internalTryGet(this, method, result); |
629 | | } |
630 | | |
631 | | protected: |
632 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
633 | | |
634 | | LdapUnbindRequestLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
635 | | Packet* packet) |
636 | 1.32k | : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
637 | 1.32k | {} |
638 | | }; |
639 | | |
640 | | /// @class LdapSearchRequestLayer |
641 | | /// Represents LDAP search request operation |
642 | | class LdapSearchRequestLayer : public LdapLayer |
643 | | { |
644 | | public: |
645 | | /// @class SearchRequestScope |
646 | | /// An enum wrapper class for LDAP search request scope |
647 | | class SearchRequestScope |
648 | | { |
649 | | public: |
650 | | /// Define enum types and the corresponding int values |
651 | | enum Value : uint8_t |
652 | | { |
653 | | /// The search operation should only be performed against the entry specified as the search base DN |
654 | | BaseObject = 0, |
655 | | /// The search operation should only be performed against entries that are immediate subordinates |
656 | | /// of the entry specified as the search base DN |
657 | | SingleLevel = 1, |
658 | | /// The search operation should be performed against the entry specified as the search base |
659 | | /// and all of its subordinates to any depth |
660 | | WholeSubtree = 2, |
661 | | /// The search operation should be performed against any subordinate entries (to any depth) below the |
662 | | /// entry specified by the base DN should be considered, but the base entry itself |
663 | | /// should not be considered |
664 | | subordinateSubtree = 3, |
665 | | /// Unknown or unsupported scope |
666 | | Unknown = 255 |
667 | | }; |
668 | | |
669 | | SearchRequestScope() = default; |
670 | | |
671 | | // cppcheck-suppress noExplicitConstructor |
672 | | /// Construct SearchRequestScope from Value enum |
673 | | /// @param[in] value the scope enum value |
674 | 640 | constexpr SearchRequestScope(Value value) : m_Value(value) |
675 | 640 | {} |
676 | | |
677 | | /// @return A string representation of the scope value |
678 | | std::string toString() const; |
679 | | |
680 | | /// A static method that creates SearchRequestScope from an integer value |
681 | | /// @param[in] value The scope integer value |
682 | | /// @return The scope that corresponds to the integer value. If the integer value |
683 | | /// doesn't corresponds to any enum value, SearchRequestScope::Unknown is returned |
684 | | static SearchRequestScope fromUintValue(uint8_t value); |
685 | | |
686 | | // Allow switch and comparisons. |
687 | | constexpr operator Value() const |
688 | 0 | { |
689 | 0 | return m_Value; |
690 | 0 | } |
691 | | |
692 | | // Prevent usage: if(LdapOperationType) |
693 | | explicit operator bool() const = delete; |
694 | | |
695 | | private: |
696 | | Value m_Value = SearchRequestScope::Unknown; |
697 | | }; |
698 | | |
699 | | /// @class DerefAliases |
700 | | /// An enum wrapper class for LDAP search request dereferencing aliases |
701 | | class DerefAliases |
702 | | { |
703 | | public: |
704 | | /// Define enum types and the corresponding int values |
705 | | enum Value : uint8_t |
706 | | { |
707 | | /// Never dereferences aliases |
708 | | NeverDerefAliases = 0, |
709 | | /// Dereferences aliases only after name resolution |
710 | | DerefInSearching = 1, |
711 | | /// Dereferences aliases only during name resolution |
712 | | DerefFindingBaseObj = 2, |
713 | | /// Always dereference aliases |
714 | | DerefAlways = 3, |
715 | | /// Unknown value |
716 | | Unknown = 255 |
717 | | }; |
718 | | |
719 | | DerefAliases() = default; |
720 | | |
721 | | // cppcheck-suppress noExplicitConstructor |
722 | | /// Construct DerefAliases from Value enum |
723 | | /// @param[in] value the dereference alias enum value |
724 | 0 | constexpr DerefAliases(Value value) : m_Value(value) |
725 | 0 | {} |
726 | | |
727 | | /// @return A string representation of the dereference alias value |
728 | | std::string toString() const; |
729 | | |
730 | | /// A static method that creates DerefAliases from an integer value |
731 | | /// @param[in] value The dereference alias integer value |
732 | | /// @return The dereference alias that corresponds to the integer value. If the integer value |
733 | | /// doesn't corresponds to any enum value, DerefAliases::Unknown is returned |
734 | | static DerefAliases fromUintValue(uint8_t value); |
735 | | |
736 | | // Allow switch and comparisons. |
737 | | constexpr operator Value() const |
738 | 0 | { |
739 | 0 | return m_Value; |
740 | 0 | } |
741 | | |
742 | | // Prevent usage: if(LdapOperationType) |
743 | | explicit operator bool() const = delete; |
744 | | |
745 | | private: |
746 | | Value m_Value = DerefAliases::Unknown; |
747 | | }; |
748 | | |
749 | | /// A constructor to create a new LDAP search request message |
750 | | /// @param[in] messageId The LDAP message ID |
751 | | /// @param[in] baseObject The base object for the LDAP search request entry |
752 | | /// @param[in] scope The portion of the target subtree that should be considered |
753 | | /// @param[in] derefAliases The alias dereferencing behavior, which indicates how the server should treat |
754 | | /// any aliases encountered while processing the search |
755 | | /// @param[in] sizeLimit The maximum number of entries that should be returned from the search |
756 | | /// @param[in] timeLimit The time limit for the search in seconds |
757 | | /// @param[in] typesOnly If this is given a value of true, then it indicates that entries that match the |
758 | | /// search criteria should be returned containing only the attribute descriptions for the attributes |
759 | | /// contained in that entry but should not include the values for those attributes. |
760 | | /// If this is given a value of false, then it indicates that the attribute values should be included |
761 | | /// in the entries that are returned |
762 | | /// @param[in] filterRecord The filter for the search. Please note that parsing for the search filter |
763 | | /// doesn't exist yet. Therefore, the expected input value should be a plain ASN.1 record |
764 | | /// @param[in] attributes A set of attributes to request for inclusion in entries that match the search |
765 | | /// criteria and are returned to the client |
766 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
767 | | /// will be created without LDAP controls |
768 | | LdapSearchRequestLayer(uint16_t messageId, const std::string& baseObject, SearchRequestScope scope, |
769 | | DerefAliases derefAliases, uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, |
770 | | Asn1Record* filterRecord, const std::vector<std::string>& attributes, |
771 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
772 | | |
773 | | /// @return The base object for the LDAP search request entry |
774 | | std::string getBaseObject() const; |
775 | | |
776 | | /// @return The portion of the target subtree that should be considered |
777 | | SearchRequestScope getScope() const; |
778 | | |
779 | | /// @return The alias dereferencing behavior |
780 | | DerefAliases getDerefAlias() const; |
781 | | |
782 | | /// @return The maximum number of entries that should be returned from the search |
783 | | uint8_t getSizeLimit() const; |
784 | | |
785 | | /// @return The time limit for the search in seconds |
786 | | uint8_t getTimeLimit() const; |
787 | | |
788 | | /// @return If this flag is true, then it indicates that entries that match the search criteria should be |
789 | | /// returned containing only the attribute descriptions for the attributes contained in that entry but |
790 | | /// should not include the values for those attributes. If this flag is false, then it indicates that the |
791 | | /// attribute values should be included in the entries that are returned |
792 | | bool getTypesOnly() const; |
793 | | |
794 | | /// @return The filter for the search. Please note that parsing for the search filter doesn't exist yet. |
795 | | /// Therefore, the return value is a plain ASN.1 record |
796 | | Asn1Record* getFilter() const; |
797 | | |
798 | | /// @return A list of search request attributes |
799 | | std::vector<std::string> getAttributes() const; |
800 | | |
801 | | template <typename Method, typename ResultType> bool tryGet(Method method, ResultType& result) |
802 | | { |
803 | | return internalTryGet(this, method, result); |
804 | | } |
805 | | |
806 | | protected: |
807 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
808 | | |
809 | | static constexpr int baseObjectIndex = 0; |
810 | | static constexpr int scopeIndex = 1; |
811 | | static constexpr int derefAliasIndex = 2; |
812 | | static constexpr int sizeLimitIndex = 3; |
813 | | static constexpr int timeLimitIndex = 4; |
814 | | static constexpr int typesOnlyIndex = 5; |
815 | | static constexpr int filterIndex = 6; |
816 | | static constexpr int attributesIndex = 7; |
817 | | |
818 | | LdapSearchRequestLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
819 | | Packet* packet) |
820 | 1.60k | : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
821 | 1.60k | {} |
822 | | |
823 | | std::string getExtendedInfoString() const override; |
824 | | }; |
825 | | |
826 | | /// @class LdapSearchResultEntryLayer |
827 | | /// Represents LDAP search result entry message |
828 | | class LdapSearchResultEntryLayer : public LdapLayer |
829 | | { |
830 | | public: |
831 | | /// A constructor to create a new LDAP search result entry message |
832 | | /// @param[in] messageId The LDAP message ID |
833 | | /// @param[in] objectName The entry's DN |
834 | | /// @param[in] attributes The entry's attributes |
835 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
836 | | /// will be created without LDAP controls |
837 | | LdapSearchResultEntryLayer(uint16_t messageId, const std::string& objectName, |
838 | | const std::vector<LdapAttribute>& attributes, |
839 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()); |
840 | | |
841 | | /// @return The entry's DN |
842 | | std::string getObjectName() const; |
843 | | |
844 | | /// @return The entry's attributes |
845 | | std::vector<LdapAttribute> getAttributes() const; |
846 | | |
847 | | template <typename Method, typename ResultType> bool tryGet(Method method, ResultType& result) |
848 | | { |
849 | | return internalTryGet(this, method, result); |
850 | | } |
851 | | |
852 | | protected: |
853 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
854 | | |
855 | | static constexpr int objectNameIndex = 0; |
856 | | static constexpr int attributesIndex = 1; |
857 | | static constexpr int attributeTypeIndex = 0; |
858 | | static constexpr int attributeValueIndex = 1; |
859 | | |
860 | | LdapSearchResultEntryLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, |
861 | | Layer* prevLayer, Packet* packet) |
862 | 493 | : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
863 | 493 | {} |
864 | | }; |
865 | | |
866 | | /// @class LdapSearchResultDoneLayer |
867 | | /// Represents LDAP search result done message |
868 | | class LdapSearchResultDoneLayer : public LdapResponseLayer |
869 | | { |
870 | | public: |
871 | | /// A constructor to create a new LDAP search result done message |
872 | | /// @param[in] messageId The LDAP message ID |
873 | | /// @param[in] resultCode The LDAP result code |
874 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
875 | | /// pass an empty string |
876 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
877 | | /// pass an empty string |
878 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
879 | | /// parameter. If not provided then referral won't be added to the message |
880 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
881 | | /// will be created without LDAP controls |
882 | | LdapSearchResultDoneLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
883 | | const std::string& diagnosticMessage, |
884 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
885 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
886 | | : LdapResponseLayer(messageId, LdapOperationType::SearchResultDone, resultCode, matchedDN, |
887 | | diagnosticMessage, referral, controls) |
888 | 0 | {} |
889 | | |
890 | | protected: |
891 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
892 | | |
893 | | LdapSearchResultDoneLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, |
894 | | Layer* prevLayer, Packet* packet) |
895 | 2.33k | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
896 | 2.33k | {} |
897 | | }; |
898 | | |
899 | | /// @class LdapModifyResponseLayer |
900 | | /// Represents LDAP modify response message |
901 | | class LdapModifyResponseLayer : public LdapResponseLayer |
902 | | { |
903 | | public: |
904 | | /// A constructor to create a new LDAP modify response message |
905 | | /// @param[in] messageId The LDAP message ID |
906 | | /// @param[in] resultCode The LDAP result code |
907 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
908 | | /// pass an empty string |
909 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
910 | | /// pass an empty string |
911 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
912 | | /// parameter. If not provided then referral won't be added to the message |
913 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
914 | | /// will be created without LDAP controls |
915 | | LdapModifyResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
916 | | const std::string& diagnosticMessage, |
917 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
918 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
919 | | : LdapResponseLayer(messageId, LdapOperationType::ModifyResponse, resultCode, matchedDN, diagnosticMessage, |
920 | | referral, controls) |
921 | 0 | {} |
922 | | |
923 | | protected: |
924 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
925 | | |
926 | | LdapModifyResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
927 | | Packet* packet) |
928 | 830 | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
929 | 830 | {} |
930 | | }; |
931 | | |
932 | | /// @class LdapAddResponseLayer |
933 | | /// Represents LDAP add response message |
934 | | class LdapAddResponseLayer : public LdapResponseLayer |
935 | | { |
936 | | public: |
937 | | /// A constructor to create a new LDAP add response message |
938 | | /// @param[in] messageId The LDAP message ID |
939 | | /// @param[in] resultCode The LDAP result code |
940 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
941 | | /// pass an empty string |
942 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
943 | | /// pass an empty string |
944 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
945 | | /// parameter. If not provided then referral won't be added to the message |
946 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
947 | | /// will be created without LDAP controls |
948 | | LdapAddResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
949 | | const std::string& diagnosticMessage, |
950 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
951 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
952 | | : LdapResponseLayer(messageId, LdapOperationType::AddResponse, resultCode, matchedDN, diagnosticMessage, |
953 | | referral, controls) |
954 | 0 | {} |
955 | | |
956 | | protected: |
957 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
958 | | |
959 | | LdapAddResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
960 | | Packet* packet) |
961 | 155 | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
962 | 155 | {} |
963 | | }; |
964 | | |
965 | | /// @class LdapDeleteResponseLayer |
966 | | /// Represents LDAP delete response message |
967 | | class LdapDeleteResponseLayer : public LdapResponseLayer |
968 | | { |
969 | | public: |
970 | | /// A constructor to create a new LDAP delete response message |
971 | | /// @param[in] messageId The LDAP message ID |
972 | | /// @param[in] resultCode The LDAP result code |
973 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
974 | | /// pass an empty string |
975 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
976 | | /// pass an empty string |
977 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
978 | | /// parameter. If not provided then referral won't be added to the message |
979 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
980 | | /// will be created without LDAP controls |
981 | | LdapDeleteResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
982 | | const std::string& diagnosticMessage, |
983 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
984 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
985 | | : LdapResponseLayer(messageId, LdapOperationType::DeleteResponse, resultCode, matchedDN, diagnosticMessage, |
986 | | referral, controls) |
987 | 0 | {} |
988 | | |
989 | | protected: |
990 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
991 | | |
992 | | LdapDeleteResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, |
993 | | Packet* packet) |
994 | 335 | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
995 | 335 | {} |
996 | | }; |
997 | | |
998 | | /// @class LdapModifyDNResponseLayer |
999 | | /// Represents LDAP modify DN response message |
1000 | | class LdapModifyDNResponseLayer : public LdapResponseLayer |
1001 | | { |
1002 | | public: |
1003 | | /// A constructor to create a new LDAP modify DN response message |
1004 | | /// @param[in] messageId The LDAP message ID |
1005 | | /// @param[in] resultCode The LDAP result code |
1006 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
1007 | | /// pass an empty string |
1008 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
1009 | | /// pass an empty string |
1010 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
1011 | | /// parameter. If not provided then referral won't be added to the message |
1012 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
1013 | | /// will be created without LDAP controls |
1014 | | LdapModifyDNResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
1015 | | const std::string& diagnosticMessage, |
1016 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
1017 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
1018 | | : LdapResponseLayer(messageId, LdapOperationType::ModifyDNResponse, resultCode, matchedDN, |
1019 | | diagnosticMessage, referral, controls) |
1020 | 0 | {} |
1021 | | |
1022 | | protected: |
1023 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
1024 | | |
1025 | | LdapModifyDNResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, |
1026 | | Layer* prevLayer, Packet* packet) |
1027 | 715 | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
1028 | 715 | {} |
1029 | | }; |
1030 | | |
1031 | | /// @class LdapCompareResponseLayer |
1032 | | /// Represents LDAP compare response message |
1033 | | class LdapCompareResponseLayer : public LdapResponseLayer |
1034 | | { |
1035 | | public: |
1036 | | /// A constructor to create a new LDAP compare response message |
1037 | | /// @param[in] messageId The LDAP message ID |
1038 | | /// @param[in] resultCode The LDAP result code |
1039 | | /// @param[in] matchedDN The distinguished name (DN) to set on the message. If not applicable |
1040 | | /// pass an empty string |
1041 | | /// @param[in] diagnosticMessage The additional information to set on the message. If not applicable |
1042 | | /// pass an empty string |
1043 | | /// @param[in] referral A list of URIs to re-try the operation somewhere else. This is an optional |
1044 | | /// parameter. If not provided then referral won't be added to the message |
1045 | | /// @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message |
1046 | | /// will be created without LDAP controls |
1047 | | LdapCompareResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, |
1048 | | const std::string& diagnosticMessage, |
1049 | | const std::vector<std::string>& referral = std::vector<std::string>(), |
1050 | | const std::vector<LdapControl>& controls = std::vector<LdapControl>()) |
1051 | | : LdapResponseLayer(messageId, LdapOperationType::CompareResponse, resultCode, matchedDN, diagnosticMessage, |
1052 | | referral, controls) |
1053 | 0 | {} |
1054 | | |
1055 | | protected: |
1056 | | friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); |
1057 | | |
1058 | | LdapCompareResponseLayer(std::unique_ptr<Asn1Record> asn1Record, uint8_t* data, size_t dataLen, |
1059 | | Layer* prevLayer, Packet* packet) |
1060 | 945 | : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) |
1061 | 945 | {} |
1062 | | }; |
1063 | | |
1064 | | inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapControl& control) |
1065 | 0 | { |
1066 | 0 | os << "{" << control.controlType << ", " << control.controlValue << "}"; |
1067 | 0 | return os; |
1068 | 0 | } |
1069 | | |
1070 | | inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapAttribute& attr) |
1071 | 0 | { |
1072 | 0 | os << "{" << attr.type << ", {"; |
1073 | 0 |
|
1074 | 0 | std::string separator; |
1075 | 0 | for (const auto& value : attr.values) |
1076 | 0 | { |
1077 | 0 | os << separator << value; |
1078 | 0 | if (separator.empty()) |
1079 | 0 | { |
1080 | 0 | separator = ", "; |
1081 | 0 | } |
1082 | 0 | } |
1083 | 0 |
|
1084 | 0 | os << "}}"; |
1085 | 0 | return os; |
1086 | 0 | } |
1087 | | |
1088 | | inline std::ostream& operator<<(std::ostream& os, |
1089 | | const pcpp::LdapBindRequestLayer::SaslAuthentication& saslAuthentication) |
1090 | 0 | { |
1091 | 0 | os << "{" << saslAuthentication.mechanism << ", {"; |
1092 | 0 |
|
1093 | 0 | std::string separator; |
1094 | 0 | for (const auto& value : saslAuthentication.credentials) |
1095 | 0 | { |
1096 | 0 | os << separator << "0x" << std::hex << static_cast<int>(value) << std::dec; |
1097 | 0 | if (separator.empty()) |
1098 | 0 | { |
1099 | 0 | separator = ", "; |
1100 | 0 | } |
1101 | 0 | } |
1102 | 0 |
|
1103 | 0 | os << "}}"; |
1104 | 0 | return os; |
1105 | 0 | } |
1106 | | } // namespace pcpp |