1 /*
2   This file is part of libkldap.
3   SPDX-FileCopyrightText: 2004-2006 Szombathelyi György <gyurco@freemail.hu>
4 
5   SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #pragma once
9 
10 #include "kldap_export.h"
11 #include "ldapconnection.h"
12 #include "ldapcontrol.h"
13 #include "ldapdn.h"
14 #include "ldapobject.h"
15 #include "ldapserver.h"
16 #include "ldapurl.h"
17 
18 #include <QByteArray>
19 #include <QList>
20 #include <QString>
21 
22 #include <memory>
23 
24 namespace KLDAP
25 {
26 /**
27  * @brief
28  * This class allows sending an ldap operation
29  * (search, rename, modify, delete, compare, exop) to an LDAP server.
30  */
31 class KLDAP_EXPORT LdapOperation
32 {
33 public:
34     using ModType = enum { Mod_None, Mod_Add, Mod_Replace, Mod_Del };
35 
36     using ResultType = enum {
37         RES_BIND = 0x61,
38         RES_SEARCH_ENTRY = 0x64,
39         RES_SEARCH_REFERENCE = 0x73,
40         RES_SEARCH_RESULT = 0x65,
41         RES_MODIFY = 0x67,
42         RES_ADD = 0x69,
43         RES_DELETE = 0x69,
44         RES_MODDN = 0x6d,
45         RES_COMPARE = 0x6f,
46         RES_EXTENDED = 0x78,
47         RES_EXTENDED_PARTIAL = 0x79
48     };
49 
50     using ModOp = struct {
51         ModType type;
52         QString attr;
53         QList<QByteArray> values;
54     };
55 
56     using ModOps = QVector<ModOp>;
57 
58     enum SASL_Fields { SASL_Authname = 0x1, SASL_Authzid = 0x2, SASL_Realm = 0x4, SASL_Password = 0x8 };
59 
60     struct SASL_Credentials {
61         int fields;
62         QString authname;
63         QString authzid;
64         QString realm;
65         QString password;
66     };
67 
68     using SASL_Callback_Proc = int(SASL_Credentials &, void *);
69 
70     struct SASL_Data {
71         SASL_Callback_Proc *proc;
72         void *data;
73         SASL_Credentials creds;
74     };
75 
76     LdapOperation();
77     LdapOperation(LdapConnection &conn);
78     ~LdapOperation();
79 
80     /**
81      * Sets the connection object. Without living connection object,
82      * LDAP operations are not possible.
83      * @param the connection object to set
84      */
85     void setConnection(LdapConnection &conn);
86     /**
87      * Returns the connection object.
88      */
89     LdapConnection &connection();
90     /**
91      * Sets the client controls which will sent with each operation.
92      */
93     void setClientControls(const LdapControls &ctrls);
94     /**
95      * Sets the server controls which will sent with each operation.
96      */
97     void setServerControls(const LdapControls &ctrls);
98     /**
99      * Returns the client controls (which set by setClientControls()).
100      */
101     Q_REQUIRED_RESULT LdapControls clientControls() const;
102     /**
103      * Returns the server controls (which set by setServerControls()).
104      */
105     Q_REQUIRED_RESULT LdapControls serverControls() const;
106 
107     /**
108      * Binds to the server which specified in the connection object.
109      * Can do simple or SASL bind. Returns a message id if successful, negative value if not.
110      */
111     Q_REQUIRED_RESULT int bind(const QByteArray &creds = QByteArray(), SASL_Callback_Proc *saslproc = nullptr, void *data = nullptr);
112 
113     /**
114      * Binds to the server which specified in the connection object.
115      * Can do simple or SASL bind. This is the synchronous version.
116      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
117      */
118     Q_REQUIRED_RESULT int bind_s(SASL_Callback_Proc *saslproc = nullptr, void *data = nullptr);
119 
120     /**
121      * Starts a search operation with the given base DN, scope, filter and
122      * result attributes. Returns a message id if successful, -1 if not.
123      */
124     Q_REQUIRED_RESULT int search(const LdapDN &base, LdapUrl::Scope scope, const QString &filter, const QStringList &attrs);
125     /**
126      * Starts an addition operation.
127      * Returns a message id if successful, -1 if not.
128      * @param object the additional operation to start
129      */
130     Q_REQUIRED_RESULT int add(const LdapObject &object);
131     /**
132      * Adds the specified object to the LDAP database.
133      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
134      * @param object the object to add to LDAP database
135      */
136     Q_REQUIRED_RESULT int add_s(const LdapObject &object);
137     /**
138      * Starts an addition operation. This version accepts ModOps not LdapObject.
139      * Returns a message id if successful, -1 if not.
140      * @param dn the LdapDN operation to start
141      * @param ops the ModOps operation to start
142      */
143     Q_REQUIRED_RESULT int add(const LdapDN &dn, const ModOps &ops);
144     /**
145      * Adds the specified object to the LDAP database. This version accepts ModOps not LdapObject.
146      * This is the synchronous version.
147      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
148      * @param dn the LdapDN object to add
149      * @param ops the ModOps object to add
150      */
151     Q_REQUIRED_RESULT int add_s(const LdapDN &dn, const ModOps &ops);
152     /**
153      * Starts a modrdn operation on given DN, changing its RDN to newRdn,
154      * changing its parent to newSuperior (if it's not empty), and deletes
155      * the old dn if deleteold is true.
156      * Returns a message id if successful, -1 if not.
157      */
158     Q_REQUIRED_RESULT int rename(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold = true);
159     /**
160      * Performs a modrdn operation on given DN, changing its RDN to newRdn,
161      * changing its parent to newSuperior (if it's not empty), and deletes
162      * the old dn if deleteold is true. This is the synchronous version.
163      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
164      */
165     Q_REQUIRED_RESULT int rename_s(const LdapDN &dn, const QString &newRdn, const QString &newSuperior, bool deleteold = true);
166     /**
167      * Starts a delete operation on the given DN.
168      * Returns a message id if successful, -1 if not.
169      */
170     Q_REQUIRED_RESULT int del(const LdapDN &dn);
171     /**
172      * Deletes the given DN. This is the synchronous version.
173      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
174      * @param dn the dn to delete
175      */
176     Q_REQUIRED_RESULT int del_s(const LdapDN &dn);
177     /**
178      * Starts a modify operation on the given DN.
179      * Returns a message id if successful, -1 if not.
180      * @param dn the DN to start modify operation on
181      */
182     Q_REQUIRED_RESULT int modify(const LdapDN &dn, const ModOps &ops);
183     /**
184      * Performs a modify operation on the given DN.
185      * This is the synchronous version.
186      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
187      */
188     Q_REQUIRED_RESULT int modify_s(const LdapDN &dn, const ModOps &ops);
189     /**
190      * Starts a compare operation on the given DN, compares the specified
191      * attribute with the given value.
192      * Returns a message id if successful, -1 if not.
193      */
194     Q_REQUIRED_RESULT int compare(const LdapDN &dn, const QString &attr, const QByteArray &value);
195     /**
196      * Performs a compare operation on the given DN, compares the specified
197      * attribute with the given value. This is the synchronous version.
198      * Returns KLDAP_COMPARE_TRUE if the entry contains the attribute value
199      * and KLDAP_COMPARE_FALSE if it does not. Otherwise, some error code
200      * is returned.
201      */
202     Q_REQUIRED_RESULT int compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value);
203     /**
204      * Starts an extended operation specified with oid and data.
205      * Returns a message id if successful, -1 if not.
206      */
207     Q_REQUIRED_RESULT int exop(const QString &oid, const QByteArray &data);
208     /**
209      * Performs an extended operation specified with oid and data.
210      * This is the synchronous version.
211      * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
212      */
213     Q_REQUIRED_RESULT int exop_s(const QString &oid, const QByteArray &data);
214     /**
215      * Abandons a long-running operation. Requires the message id.
216      */
217     Q_REQUIRED_RESULT int abandon(int id);
218     /**
219      * Waits for up to \p msecs milliseconds for a result message from the LDAP
220      * server. If \p msecs is -1, then this function will block indefinitely.
221      * If \p msecs is 0, then this function will return immediately, that is it
222      * will perform a poll for a result message.
223      *
224      * Returns the type of the result LDAP message (RES_XXX constants).
225      * -1 if error occurred, 0 if the timeout value elapsed. Note!
226      * Return code -1 means that fetching the message resulted in error,
227      * not the LDAP operation error. Call connection().ldapErrorCode() to
228      * determine if the operation succeeded.
229      */
230     Q_REQUIRED_RESULT int waitForResult(int id, int msecs = -1);
231     /**
232      * Returns the result object if result() returned RES_SEARCH_ENTRY.
233      */
234     Q_REQUIRED_RESULT LdapObject object() const;
235     /**
236      * Returns the server controls from the returned ldap message (grabbed
237      * by result()).
238      */
239     Q_REQUIRED_RESULT LdapControls controls() const;
240     /**
241      * Returns the OID of the extended operation response (result
242      * returned RES_EXTENDED).
243      */
244     Q_REQUIRED_RESULT QByteArray extendedOid() const;
245     /**
246      * Returns the data from the extended operation response (result
247      * returned RES_EXTENDED).
248      */
249     Q_REQUIRED_RESULT QByteArray extendedData() const;
250     /**
251      * The server might supply a matched DN string in the message indicating
252      * how much of a name in a request was recognized. This can be grabbed by
253      * matchedDn().
254      */
255     Q_REQUIRED_RESULT QString matchedDn() const;
256     /**
257      * This function returns the referral strings from the parsed message
258      * (if any).
259      */
260     Q_REQUIRED_RESULT QList<QByteArray> referrals() const;
261     /**
262      * Returns the server response for a bind request (result
263      * returned RES_BIND).
264      */
265     Q_REQUIRED_RESULT QByteArray serverCred() const;
266 
267 private:
268     class LdapOperationPrivate;
269     std::unique_ptr<LdapOperationPrivate> const d;
270 
271     Q_DISABLE_COPY(LdapOperation)
272 };
273 }
274 
275