1"""
2"""
3
4# Created on 2014.05.14
5#
6# Author: Giovanni Cannata
7#
8# Copyright 2014 - 2020 Giovanni Cannata
9#
10# This file is part of ldap3.
11#
12# ldap3 is free software: you can redistribute it and/or modify
13# it under the terms of the GNU Lesser General Public License as published
14# by the Free Software Foundation, either version 3 of the License, or
15# (at your option) any later version.
16#
17# ldap3 is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU Lesser General Public License for more details.
21#
22# You should have received a copy of the GNU Lesser General Public License
23# along with ldap3 in the COPYING and COPYING.LESSER files.
24# If not, see <http://www.gnu.org/licenses/>.
25
26from os import sep
27from .results import RESULT_OPERATIONS_ERROR, RESULT_PROTOCOL_ERROR, RESULT_TIME_LIMIT_EXCEEDED, RESULT_SIZE_LIMIT_EXCEEDED, \
28    RESULT_STRONGER_AUTH_REQUIRED, RESULT_REFERRAL, RESULT_ADMIN_LIMIT_EXCEEDED, RESULT_UNAVAILABLE_CRITICAL_EXTENSION, \
29    RESULT_AUTH_METHOD_NOT_SUPPORTED, RESULT_UNDEFINED_ATTRIBUTE_TYPE, RESULT_NO_SUCH_ATTRIBUTE, \
30    RESULT_SASL_BIND_IN_PROGRESS, RESULT_CONFIDENTIALITY_REQUIRED, RESULT_INAPPROPRIATE_MATCHING, \
31    RESULT_CONSTRAINT_VIOLATION, \
32    RESULT_ATTRIBUTE_OR_VALUE_EXISTS, RESULT_INVALID_ATTRIBUTE_SYNTAX, RESULT_NO_SUCH_OBJECT, RESULT_ALIAS_PROBLEM, \
33    RESULT_INVALID_DN_SYNTAX, RESULT_ALIAS_DEREFERENCING_PROBLEM, RESULT_INVALID_CREDENTIALS, RESULT_LOOP_DETECTED, \
34    RESULT_ENTRY_ALREADY_EXISTS, RESULT_LCUP_SECURITY_VIOLATION, RESULT_CANCELED, RESULT_E_SYNC_REFRESH_REQUIRED, \
35    RESULT_NO_SUCH_OPERATION, RESULT_LCUP_INVALID_DATA, RESULT_OBJECT_CLASS_MODS_PROHIBITED, RESULT_NAMING_VIOLATION, \
36    RESULT_INSUFFICIENT_ACCESS_RIGHTS, RESULT_OBJECT_CLASS_VIOLATION, RESULT_TOO_LATE, RESULT_CANNOT_CANCEL, \
37    RESULT_LCUP_UNSUPPORTED_SCHEME, RESULT_BUSY, RESULT_AFFECT_MULTIPLE_DSAS, RESULT_UNAVAILABLE, \
38    RESULT_NOT_ALLOWED_ON_NON_LEAF, \
39    RESULT_UNWILLING_TO_PERFORM, RESULT_OTHER, RESULT_LCUP_RELOAD_REQUIRED, RESULT_ASSERTION_FAILED, \
40    RESULT_AUTHORIZATION_DENIED, RESULT_LCUP_RESOURCES_EXHAUSTED, RESULT_NOT_ALLOWED_ON_RDN, \
41    RESULT_INAPPROPRIATE_AUTHENTICATION
42import socket
43
44
45# LDAPException hierarchy
46class LDAPException(Exception):
47    pass
48
49
50class LDAPOperationResult(LDAPException):
51    def __new__(cls, result=None, description=None, dn=None, message=None, response_type=None, response=None):
52        if cls is LDAPOperationResult and result and result in exception_table:
53            exc = super(LDAPOperationResult, exception_table[result]).__new__(
54                exception_table[result])  # create an exception of the required result error
55            exc.result = result
56            exc.description = description
57            exc.dn = dn
58            exc.message = message
59            exc.type = response_type
60            exc.response = response
61        else:
62            exc = super(LDAPOperationResult, cls).__new__(cls)
63        return exc
64
65    def __init__(self, result=None, description=None, dn=None, message=None, response_type=None, response=None):
66        self.result = result
67        self.description = description
68        self.dn = dn
69        self.message = message
70        self.type = response_type
71        self.response = response
72
73    def __str__(self):
74        s = [self.__class__.__name__,
75             str(self.result) if self.result else None,
76             self.description if self.description else None,
77             self.dn if self.dn else None,
78             self.message if self.message else None,
79             self.type if self.type else None,
80             self.response if self.response else None]
81
82        return ' - '.join([str(item) for item in s if s is not None])
83
84    def __repr__(self):
85        return self.__str__()
86
87
88class LDAPOperationsErrorResult(LDAPOperationResult):
89    pass
90
91
92class LDAPProtocolErrorResult(LDAPOperationResult):
93    pass
94
95
96class LDAPTimeLimitExceededResult(LDAPOperationResult):
97    pass
98
99
100class LDAPSizeLimitExceededResult(LDAPOperationResult):
101    pass
102
103
104class LDAPAuthMethodNotSupportedResult(LDAPOperationResult):
105    pass
106
107
108class LDAPStrongerAuthRequiredResult(LDAPOperationResult):
109    pass
110
111
112class LDAPReferralResult(LDAPOperationResult):
113    pass
114
115
116class LDAPAdminLimitExceededResult(LDAPOperationResult):
117    pass
118
119
120class LDAPUnavailableCriticalExtensionResult(LDAPOperationResult):
121    pass
122
123
124class LDAPConfidentialityRequiredResult(LDAPOperationResult):
125    pass
126
127
128class LDAPSASLBindInProgressResult(LDAPOperationResult):
129    pass
130
131
132class LDAPNoSuchAttributeResult(LDAPOperationResult):
133    pass
134
135
136class LDAPUndefinedAttributeTypeResult(LDAPOperationResult):
137    pass
138
139
140class LDAPInappropriateMatchingResult(LDAPOperationResult):
141    pass
142
143
144class LDAPConstraintViolationResult(LDAPOperationResult):
145    pass
146
147
148class LDAPAttributeOrValueExistsResult(LDAPOperationResult):
149    pass
150
151
152class LDAPInvalidAttributeSyntaxResult(LDAPOperationResult):
153    pass
154
155
156class LDAPNoSuchObjectResult(LDAPOperationResult):
157    pass
158
159
160class LDAPAliasProblemResult(LDAPOperationResult):
161    pass
162
163
164class LDAPInvalidDNSyntaxResult(LDAPOperationResult):
165    pass
166
167
168class LDAPAliasDereferencingProblemResult(LDAPOperationResult):
169    pass
170
171
172class LDAPInappropriateAuthenticationResult(LDAPOperationResult):
173    pass
174
175
176class LDAPInvalidCredentialsResult(LDAPOperationResult):
177    pass
178
179
180class LDAPInsufficientAccessRightsResult(LDAPOperationResult):
181    pass
182
183
184class LDAPBusyResult(LDAPOperationResult):
185    pass
186
187
188class LDAPUnavailableResult(LDAPOperationResult):
189    pass
190
191
192class LDAPUnwillingToPerformResult(LDAPOperationResult):
193    pass
194
195
196class LDAPLoopDetectedResult(LDAPOperationResult):
197    pass
198
199
200class LDAPNamingViolationResult(LDAPOperationResult):
201    pass
202
203
204class LDAPObjectClassViolationResult(LDAPOperationResult):
205    pass
206
207
208class LDAPNotAllowedOnNotLeafResult(LDAPOperationResult):
209    pass
210
211
212class LDAPNotAllowedOnRDNResult(LDAPOperationResult):
213    pass
214
215
216class LDAPEntryAlreadyExistsResult(LDAPOperationResult):
217    pass
218
219
220class LDAPObjectClassModsProhibitedResult(LDAPOperationResult):
221    pass
222
223
224class LDAPAffectMultipleDSASResult(LDAPOperationResult):
225    pass
226
227
228class LDAPOtherResult(LDAPOperationResult):
229    pass
230
231
232class LDAPLCUPResourcesExhaustedResult(LDAPOperationResult):
233    pass
234
235
236class LDAPLCUPSecurityViolationResult(LDAPOperationResult):
237    pass
238
239
240class LDAPLCUPInvalidDataResult(LDAPOperationResult):
241    pass
242
243
244class LDAPLCUPUnsupportedSchemeResult(LDAPOperationResult):
245    pass
246
247
248class LDAPLCUPReloadRequiredResult(LDAPOperationResult):
249    pass
250
251
252class LDAPCanceledResult(LDAPOperationResult):
253    pass
254
255
256class LDAPNoSuchOperationResult(LDAPOperationResult):
257    pass
258
259
260class LDAPTooLateResult(LDAPOperationResult):
261    pass
262
263
264class LDAPCannotCancelResult(LDAPOperationResult):
265    pass
266
267
268class LDAPAssertionFailedResult(LDAPOperationResult):
269    pass
270
271
272class LDAPAuthorizationDeniedResult(LDAPOperationResult):
273    pass
274
275
276class LDAPESyncRefreshRequiredResult(LDAPOperationResult):
277    pass
278
279
280exception_table = {RESULT_OPERATIONS_ERROR: LDAPOperationsErrorResult,
281                   RESULT_PROTOCOL_ERROR: LDAPProtocolErrorResult,
282                   RESULT_TIME_LIMIT_EXCEEDED: LDAPTimeLimitExceededResult,
283                   RESULT_SIZE_LIMIT_EXCEEDED: LDAPSizeLimitExceededResult,
284                   RESULT_AUTH_METHOD_NOT_SUPPORTED: LDAPAuthMethodNotSupportedResult,
285                   RESULT_STRONGER_AUTH_REQUIRED: LDAPStrongerAuthRequiredResult,
286                   RESULT_REFERRAL: LDAPReferralResult,
287                   RESULT_ADMIN_LIMIT_EXCEEDED: LDAPAdminLimitExceededResult,
288                   RESULT_UNAVAILABLE_CRITICAL_EXTENSION: LDAPUnavailableCriticalExtensionResult,
289                   RESULT_CONFIDENTIALITY_REQUIRED: LDAPConfidentialityRequiredResult,
290                   RESULT_SASL_BIND_IN_PROGRESS: LDAPSASLBindInProgressResult,
291                   RESULT_NO_SUCH_ATTRIBUTE: LDAPNoSuchAttributeResult,
292                   RESULT_UNDEFINED_ATTRIBUTE_TYPE: LDAPUndefinedAttributeTypeResult,
293                   RESULT_INAPPROPRIATE_MATCHING: LDAPInappropriateMatchingResult,
294                   RESULT_CONSTRAINT_VIOLATION: LDAPConstraintViolationResult,
295                   RESULT_ATTRIBUTE_OR_VALUE_EXISTS: LDAPAttributeOrValueExistsResult,
296                   RESULT_INVALID_ATTRIBUTE_SYNTAX: LDAPInvalidAttributeSyntaxResult,
297                   RESULT_NO_SUCH_OBJECT: LDAPNoSuchObjectResult,
298                   RESULT_ALIAS_PROBLEM: LDAPAliasProblemResult,
299                   RESULT_INVALID_DN_SYNTAX: LDAPInvalidDNSyntaxResult,
300                   RESULT_ALIAS_DEREFERENCING_PROBLEM: LDAPAliasDereferencingProblemResult,
301                   RESULT_INAPPROPRIATE_AUTHENTICATION: LDAPInappropriateAuthenticationResult,
302                   RESULT_INVALID_CREDENTIALS: LDAPInvalidCredentialsResult,
303                   RESULT_INSUFFICIENT_ACCESS_RIGHTS: LDAPInsufficientAccessRightsResult,
304                   RESULT_BUSY: LDAPBusyResult,
305                   RESULT_UNAVAILABLE: LDAPUnavailableResult,
306                   RESULT_UNWILLING_TO_PERFORM: LDAPUnwillingToPerformResult,
307                   RESULT_LOOP_DETECTED: LDAPLoopDetectedResult,
308                   RESULT_NAMING_VIOLATION: LDAPNamingViolationResult,
309                   RESULT_OBJECT_CLASS_VIOLATION: LDAPObjectClassViolationResult,
310                   RESULT_NOT_ALLOWED_ON_NON_LEAF: LDAPNotAllowedOnNotLeafResult,
311                   RESULT_NOT_ALLOWED_ON_RDN: LDAPNotAllowedOnRDNResult,
312                   RESULT_ENTRY_ALREADY_EXISTS: LDAPEntryAlreadyExistsResult,
313                   RESULT_OBJECT_CLASS_MODS_PROHIBITED: LDAPObjectClassModsProhibitedResult,
314                   RESULT_AFFECT_MULTIPLE_DSAS: LDAPAffectMultipleDSASResult,
315                   RESULT_OTHER: LDAPOtherResult,
316                   RESULT_LCUP_RESOURCES_EXHAUSTED: LDAPLCUPResourcesExhaustedResult,
317                   RESULT_LCUP_SECURITY_VIOLATION: LDAPLCUPSecurityViolationResult,
318                   RESULT_LCUP_INVALID_DATA: LDAPLCUPInvalidDataResult,
319                   RESULT_LCUP_UNSUPPORTED_SCHEME: LDAPLCUPUnsupportedSchemeResult,
320                   RESULT_LCUP_RELOAD_REQUIRED: LDAPLCUPReloadRequiredResult,
321                   RESULT_CANCELED: LDAPCanceledResult,
322                   RESULT_NO_SUCH_OPERATION: LDAPNoSuchOperationResult,
323                   RESULT_TOO_LATE: LDAPTooLateResult,
324                   RESULT_CANNOT_CANCEL: LDAPCannotCancelResult,
325                   RESULT_ASSERTION_FAILED: LDAPAssertionFailedResult,
326                   RESULT_AUTHORIZATION_DENIED: LDAPAuthorizationDeniedResult,
327                   RESULT_E_SYNC_REFRESH_REQUIRED: LDAPESyncRefreshRequiredResult}
328
329
330class LDAPExceptionError(LDAPException):
331    pass
332
333
334# configuration exceptions
335class LDAPConfigurationError(LDAPExceptionError):
336    pass
337
338
339class LDAPUnknownStrategyError(LDAPConfigurationError):
340    pass
341
342
343class LDAPUnknownAuthenticationMethodError(LDAPConfigurationError):
344    pass
345
346
347class LDAPSSLConfigurationError(LDAPConfigurationError):
348    pass
349
350
351class LDAPDefinitionError(LDAPConfigurationError):
352    pass
353
354
355class LDAPPackageUnavailableError(LDAPConfigurationError, ImportError):
356    pass
357
358
359class LDAPConfigurationParameterError(LDAPConfigurationError):
360    pass
361
362
363# abstract layer exceptions
364class LDAPKeyError(LDAPExceptionError, KeyError, AttributeError):
365    pass
366
367
368class LDAPObjectError(LDAPExceptionError, ValueError):
369    pass
370
371
372class LDAPAttributeError(LDAPExceptionError, ValueError, TypeError):
373    pass
374
375
376class LDAPCursorError(LDAPExceptionError):
377    pass
378
379
380class LDAPCursorAttributeError(LDAPCursorError, AttributeError):
381    pass
382
383
384class LDAPObjectDereferenceError(LDAPExceptionError):
385    pass
386
387
388# security exceptions
389class LDAPSSLNotSupportedError(LDAPExceptionError, ImportError):
390    pass
391
392
393class LDAPInvalidTlsSpecificationError(LDAPExceptionError):
394    pass
395
396
397class LDAPInvalidHashAlgorithmError(LDAPExceptionError, ValueError):
398    pass
399
400
401# connection exceptions
402class LDAPBindError(LDAPExceptionError):
403    pass
404
405
406class LDAPInvalidServerError(LDAPExceptionError):
407    pass
408
409
410class LDAPSASLMechanismNotSupportedError(LDAPExceptionError):
411    pass
412
413
414class LDAPConnectionIsReadOnlyError(LDAPExceptionError):
415    pass
416
417
418class LDAPChangeError(LDAPExceptionError, ValueError):
419    pass
420
421
422class LDAPServerPoolError(LDAPExceptionError):
423    pass
424
425
426class LDAPServerPoolExhaustedError(LDAPExceptionError):
427    pass
428
429
430class LDAPInvalidPortError(LDAPExceptionError):
431    pass
432
433
434class LDAPStartTLSError(LDAPExceptionError):
435    pass
436
437
438class LDAPCertificateError(LDAPExceptionError):
439    pass
440
441
442class LDAPUserNameNotAllowedError(LDAPExceptionError):
443    pass
444
445
446class LDAPUserNameIsMandatoryError(LDAPExceptionError):
447    pass
448
449
450class LDAPPasswordIsMandatoryError(LDAPExceptionError):
451    pass
452
453
454class LDAPInvalidFilterError(LDAPExceptionError):
455    pass
456
457
458class LDAPInvalidScopeError(LDAPExceptionError, ValueError):
459    pass
460
461
462class LDAPInvalidDereferenceAliasesError(LDAPExceptionError, ValueError):
463    pass
464
465
466class LDAPInvalidValueError(LDAPExceptionError, ValueError):
467    pass
468
469
470class LDAPControlError(LDAPExceptionError, ValueError):
471    pass
472
473
474class LDAPExtensionError(LDAPExceptionError, ValueError):
475    pass
476
477
478class LDAPLDIFError(LDAPExceptionError):
479    pass
480
481
482class LDAPSchemaError(LDAPExceptionError):
483    pass
484
485
486class LDAPSASLPrepError(LDAPExceptionError):
487    pass
488
489
490class LDAPSASLBindInProgressError(LDAPExceptionError):
491    pass
492
493
494class LDAPMetricsError(LDAPExceptionError):
495    pass
496
497
498class LDAPObjectClassError(LDAPExceptionError):
499    pass
500
501
502class LDAPInvalidDnError(LDAPExceptionError):
503    pass
504
505
506class LDAPResponseTimeoutError(LDAPExceptionError):
507    pass
508
509
510class LDAPTransactionError(LDAPExceptionError):
511    pass
512
513
514class LDAPInfoError(LDAPExceptionError):
515    pass
516
517
518# communication exceptions
519class LDAPCommunicationError(LDAPExceptionError):
520    pass
521
522
523class LDAPSocketOpenError(LDAPCommunicationError):
524    pass
525
526
527class LDAPSocketCloseError(LDAPCommunicationError):
528    pass
529
530
531class LDAPSocketReceiveError(LDAPCommunicationError, socket.error):
532    pass
533
534
535class LDAPSocketSendError(LDAPCommunicationError, socket.error):
536    pass
537
538
539class LDAPSessionTerminatedByServerError(LDAPCommunicationError):
540    pass
541
542
543class LDAPUnknownResponseError(LDAPCommunicationError):
544    pass
545
546
547class LDAPUnknownRequestError(LDAPCommunicationError):
548    pass
549
550
551class LDAPReferralError(LDAPCommunicationError):
552    pass
553
554
555# pooling exceptions
556class LDAPConnectionPoolNameIsMandatoryError(LDAPExceptionError):
557    pass
558
559
560class LDAPConnectionPoolNotStartedError(LDAPExceptionError):
561    pass
562
563
564# restartable strategy
565class LDAPMaximumRetriesError(LDAPExceptionError):
566    def __str__(self):
567        s = []
568        if self.args:
569            if isinstance(self.args, tuple):
570                if len(self.args) > 0:
571                    s.append('LDAPMaximumRetriesError: ' + str(self.args[0]))
572                if len(self.args) > 1:
573                    s.append('Exception history:')
574                    prev_exc = ''
575                    for i, exc in enumerate(self.args[1]):  # args[1] contains exception history
576                        # if str(exc[1]) != prev_exc:
577                        #     s.append((str(i).rjust(5) + ' ' + str(exc[0]) + ': ' + str(exc[1]) + ' - ' + str(exc[2])))
578                        #     prev_exc = str(exc[1])
579                        if str(exc) != prev_exc:
580                            s.append((str(i).rjust(5) + ' ' + str(type(exc)) + ': ' + str(exc)))
581                            prev_exc = str(exc)
582                if len(self.args) > 2:
583                    s.append('Maximum number of retries reached: ' + str(self.args[2]))
584        else:
585            s = [LDAPExceptionError.__str__(self)]
586
587        return sep.join(s)
588
589
590# exception factories
591def communication_exception_factory(exc_to_raise, exc):
592    """
593    Generates a new exception class of the requested type (subclass of LDAPCommunication) merged with the exception raised by the interpreter
594    """
595    if exc_to_raise.__name__ in [cls.__name__ for cls in LDAPCommunicationError.__subclasses__()]:
596        return type(exc_to_raise.__name__, (exc_to_raise, type(exc)), dict())
597    else:
598        raise LDAPExceptionError('unable to generate exception type ' + str(exc_to_raise))
599
600
601def start_tls_exception_factory(exc):
602    """
603    Generates a new exception class of the requested type merged with the exception raised by the interpreter
604    """
605    return type(LDAPStartTLSError.__name__, (LDAPStartTLSError, type(exc)), dict())
606