0
# LDAP Operations
1
2
All standard LDAP operations including search, add, modify, delete, compare, and abandon operations with full control support and multiple response formats.
3
4
## Capabilities
5
6
### Search Operations
7
8
Perform LDAP search operations with various scopes, filters, and result processing options.
9
10
```python { .api }
11
def search(self, search_base, search_filter, search_scope=SUBTREE,
12
dereference_aliases=DEREF_ALWAYS, attributes=None, size_limit=0,
13
time_limit=0, types_only=False, get_operational_attributes=False,
14
controls=None, paged_size=None, paged_criticality=False,
15
paged_cookie=None):
16
"""
17
Perform LDAP search operation.
18
19
Args:
20
search_base (str): Base DN for search
21
search_filter (str): LDAP search filter (RFC 4515)
22
search_scope (str): Search scope (BASE, LEVEL, SUBTREE)
23
dereference_aliases (str): Alias dereferencing behavior (NEVER, SEARCH, BASE, ALWAYS)
24
attributes (list, optional): Attributes to retrieve (None for all)
25
size_limit (int): Maximum number of entries to return (0 for no limit)
26
time_limit (int): Search time limit in seconds (0 for no limit)
27
types_only (bool): Return attribute types only, not values
28
get_operational_attributes (bool): Include operational attributes
29
controls (list, optional): LDAP controls for search
30
paged_size (int, optional): Page size for paged search
31
paged_criticality (bool): Paged search criticality
32
paged_cookie (bytes, optional): Paged search cookie
33
34
Returns:
35
bool: True if search successful, False otherwise
36
"""
37
```
38
39
**Search Result Access**:
40
- `connection.entries`: List of Entry objects (abstract layer)
41
- `connection.response`: Raw LDAP response
42
- `connection.result`: Operation result information
43
44
### Add Operations
45
46
Add new entries to the LDAP directory with specified object classes and attributes.
47
48
```python { .api }
49
def add(self, dn, object_class=None, attributes=None, controls=None):
50
"""
51
Add new entry to LDAP directory.
52
53
Args:
54
dn (str): Distinguished Name of new entry
55
object_class (str or list, optional): Object class(es) for entry
56
attributes (dict, optional): Entry attributes as {name: value} or {name: [values]}
57
controls (list, optional): LDAP controls for add operation
58
59
Returns:
60
bool: True if add successful, False otherwise
61
"""
62
```
63
64
### Modify Operations
65
66
Modify existing LDAP entries by adding, deleting, replacing, or incrementing attribute values.
67
68
```python { .api }
69
def modify(self, dn, changes, controls=None):
70
"""
71
Modify existing LDAP entry.
72
73
Args:
74
dn (str): Distinguished Name of entry to modify
75
changes (dict): Modifications as {attribute: [(operation, [values])]}
76
Operation: MODIFY_ADD, MODIFY_DELETE, MODIFY_REPLACE, MODIFY_INCREMENT
77
controls (list, optional): LDAP controls for modify operation
78
79
Returns:
80
bool: True if modify successful, False otherwise
81
"""
82
```
83
84
### Delete Operations
85
86
Delete entries from the LDAP directory.
87
88
```python { .api }
89
def delete(self, dn, controls=None):
90
"""
91
Delete entry from LDAP directory.
92
93
Args:
94
dn (str): Distinguished Name of entry to delete
95
controls (list, optional): LDAP controls for delete operation
96
97
Returns:
98
bool: True if delete successful, False otherwise
99
"""
100
```
101
102
### Modify DN Operations
103
104
Rename or move LDAP entries by modifying their distinguished names.
105
106
```python { .api }
107
def modify_dn(self, dn, relative_dn, delete_old_dn=True, new_superior=None, controls=None):
108
"""
109
Modify distinguished name of entry (rename/move).
110
111
Args:
112
dn (str): Current distinguished name
113
relative_dn (str): New relative distinguished name
114
delete_old_dn (bool): Delete old RDN attribute values
115
new_superior (str, optional): New parent DN for move operation
116
controls (list, optional): LDAP controls for modify DN operation
117
118
Returns:
119
bool: True if modify DN successful, False otherwise
120
"""
121
```
122
123
### Compare Operations
124
125
Compare attribute values in LDAP entries without retrieving the actual values.
126
127
```python { .api }
128
def compare(self, dn, attribute, value, controls=None):
129
"""
130
Compare attribute value in LDAP entry.
131
132
Args:
133
dn (str): Distinguished Name of entry
134
attribute (str): Attribute name to compare
135
value (str or bytes): Value to compare against
136
controls (list, optional): LDAP controls for compare operation
137
138
Returns:
139
bool: True if values match, False if different or error
140
"""
141
```
142
143
### Abandon Operations
144
145
Abandon ongoing LDAP operations using their message IDs.
146
147
```python { .api }
148
def abandon(self, message_id, controls=None):
149
"""
150
Abandon ongoing LDAP operation.
151
152
Args:
153
message_id (int): Message ID of operation to abandon
154
controls (list, optional): LDAP controls for abandon operation
155
156
Returns:
157
bool: True if abandon request sent successfully
158
"""
159
```
160
161
### Extended Operations
162
163
Perform LDAP extended operations with custom request names and values.
164
165
```python { .api }
166
def extended(self, request_name, request_value=None, controls=None):
167
"""
168
Perform LDAP extended operation.
169
170
Args:
171
request_name (str): Extended operation request name (OID)
172
request_value (bytes, optional): Extended operation request value
173
controls (list, optional): LDAP controls for extended operation
174
175
Returns:
176
bool: True if extended operation successful
177
"""
178
```
179
180
### Response Processing
181
182
Access and process LDAP operation responses in various formats.
183
184
```python { .api }
185
def response_to_ldif(self):
186
"""
187
Convert last response to LDIF format.
188
189
Returns:
190
str: Response in LDIF format
191
"""
192
193
def response_to_json(self):
194
"""
195
Convert last response to JSON format.
196
197
Returns:
198
str: Response in JSON format
199
"""
200
201
def response_to_file(self, target, raw=False):
202
"""
203
Save response to file.
204
205
Args:
206
target (str): Target file path
207
raw (bool): Save raw response vs formatted
208
"""
209
```
210
211
## Usage Examples
212
213
### Basic Search
214
215
```python
216
import ldap3
217
218
server = ldap3.Server('ldap://ldap.example.com')
219
conn = ldap3.Connection(server, 'cn=user,dc=example,dc=com', 'password', auto_bind=True)
220
221
# Search for all people
222
conn.search('dc=example,dc=com', '(objectClass=person)', attributes=['cn', 'mail', 'telephoneNumber'])
223
224
for entry in conn.entries:
225
print(f"Name: {entry.cn}")
226
print(f"Email: {entry.mail}")
227
print(f"Phone: {entry.telephoneNumber}")
228
print("---")
229
```
230
231
### Advanced Search with Filters
232
233
```python
234
# Complex search filter
235
filter_str = '(&(objectClass=person)(|(cn=John*)(mail=*@example.com)))'
236
conn.search('ou=people,dc=example,dc=com', filter_str,
237
search_scope=ldap3.LEVEL,
238
attributes=['cn', 'mail', 'description'],
239
size_limit=100)
240
241
# Access raw response
242
for response_item in conn.response:
243
if response_item['type'] == 'searchResEntry':
244
dn = response_item['dn']
245
attributes = response_item['attributes']
246
print(f"DN: {dn}")
247
print(f"Attributes: {attributes}")
248
```
249
250
### Paged Search for Large Results
251
252
```python
253
# Paged search to handle large result sets
254
search_base = 'dc=example,dc=com'
255
search_filter = '(objectClass=person)'
256
search_paged_size = 100
257
258
# Perform first page
259
conn.search(search_base, search_filter, paged_size=search_paged_size)
260
total_entries = len(conn.entries)
261
262
# Continue with additional pages
263
while True:
264
cookie = conn.result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
265
if not cookie:
266
break
267
268
conn.search(search_base, search_filter, paged_size=search_paged_size, paged_cookie=cookie)
269
total_entries += len(conn.entries)
270
271
print(f"Total entries found: {total_entries}")
272
```
273
274
### Adding Entries
275
276
```python
277
# Add new person entry
278
new_dn = 'cn=John Doe,ou=people,dc=example,dc=com'
279
attributes = {
280
'cn': 'John Doe',
281
'sn': 'Doe',
282
'givenName': 'John',
283
'mail': 'john.doe@example.com',
284
'telephoneNumber': '+1-555-1234',
285
'userPassword': 'secretpassword'
286
}
287
288
result = conn.add(new_dn, object_class=['inetOrgPerson', 'person'], attributes=attributes)
289
if result:
290
print("Entry added successfully")
291
else:
292
print(f"Failed to add entry: {conn.result}")
293
```
294
295
### Modifying Entries
296
297
```python
298
# Modify existing entry
299
target_dn = 'cn=John Doe,ou=people,dc=example,dc=com'
300
301
# Different types of modifications
302
changes = {
303
'mail': [(ldap3.MODIFY_REPLACE, 'newemail@example.com')], # Replace email
304
'telephoneNumber': [(ldap3.MODIFY_ADD, '+1-555-5678')], # Add phone number
305
'description': [(ldap3.MODIFY_DELETE, [])], # Delete all descriptions
306
'loginCount': [(ldap3.MODIFY_INCREMENT, 1)] # Increment counter
307
}
308
309
result = conn.modify(target_dn, changes)
310
if result:
311
print("Entry modified successfully")
312
else:
313
print(f"Failed to modify entry: {conn.result}")
314
```
315
316
### Complex Modify with Multiple Changes
317
318
```python
319
# Multiple attribute modifications in single operation
320
changes = {
321
'mail': [(ldap3.MODIFY_REPLACE, ['primary@example.com', 'secondary@example.com'])],
322
'telephoneNumber': [(ldap3.MODIFY_DELETE, '+1-555-1234'), # Delete specific phone
323
(ldap3.MODIFY_ADD, ['+1-555-9999', '+1-555-8888'])], # Add new phones
324
'title': [(ldap3.MODIFY_REPLACE, 'Senior Developer')]
325
}
326
327
conn.modify('cn=John Doe,ou=people,dc=example,dc=com', changes)
328
```
329
330
### Moving/Renaming Entries
331
332
```python
333
# Rename entry (change CN)
334
old_dn = 'cn=John Doe,ou=people,dc=example,dc=com'
335
new_rdn = 'cn=John Smith'
336
conn.modify_dn(old_dn, new_rdn, delete_old_dn=True)
337
338
# Move entry to different OU
339
current_dn = 'cn=John Smith,ou=people,dc=example,dc=com'
340
new_superior = 'ou=employees,dc=example,dc=com'
341
conn.modify_dn(current_dn, 'cn=John Smith', new_superior=new_superior)
342
```
343
344
### Deleting Entries
345
346
```python
347
# Delete single entry
348
entry_dn = 'cn=John Smith,ou=employees,dc=example,dc=com'
349
result = conn.delete(entry_dn)
350
if result:
351
print("Entry deleted successfully")
352
else:
353
print(f"Failed to delete entry: {conn.result}")
354
```
355
356
### Compare Operation
357
358
```python
359
# Compare attribute value without retrieving it
360
entry_dn = 'cn=admin,dc=example,dc=com'
361
result = conn.compare(entry_dn, 'userPassword', 'secretpassword')
362
if result:
363
print("Password matches")
364
elif conn.result['result'] == 5: # RESULT_COMPARE_FALSE
365
print("Password does not match")
366
else:
367
print(f"Compare operation failed: {conn.result}")
368
```
369
370
### Working with Controls
371
372
```python
373
# Search with server-side sorting control
374
from ldap3.protocol.rfc2696 import paged_search_control
375
from ldap3.protocol.rfc2891 import sort_control
376
377
# Server-side sort by cn attribute
378
sort_ctrl = sort_control([('cn', True)]) # True = ascending
379
conn.search('dc=example,dc=com', '(objectClass=person)',
380
controls=[sort_ctrl], attributes=['cn', 'mail'])
381
382
# Process sorted results
383
for entry in conn.entries:
384
print(f"{entry.cn}: {entry.mail}")
385
```
386
387
### Asynchronous Operations
388
389
```python
390
# Asynchronous connection for non-blocking operations
391
server = ldap3.Server('ldap://ldap.example.com')
392
conn = ldap3.Connection(server, 'cn=user,dc=example,dc=com', 'password',
393
client_strategy=ldap3.ASYNC, auto_bind=True)
394
395
# Start search operation (returns immediately)
396
message_id = conn.search('dc=example,dc=com', '(objectClass=person)')
397
398
# Do other work while search is running
399
import time
400
time.sleep(1)
401
402
# Get results when ready
403
result, response = conn.get_response(message_id)
404
if result:
405
for item in response:
406
if item['type'] == 'searchResEntry':
407
print(f"Found: {item['dn']}")
408
```
409
410
### Response Format Examples
411
412
```python
413
# JSON response format
414
conn.search('dc=example,dc=com', '(objectClass=person)', attributes=['cn', 'mail'])
415
json_response = conn.response_to_json()
416
print(json_response)
417
418
# LDIF response format
419
ldif_response = conn.response_to_ldif()
420
print(ldif_response)
421
422
# Save to file
423
conn.response_to_file('/tmp/search_results.ldif')
424
```