From 48a924117b3abe53a98c70d6791488b1ebafced0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 27 Nov 2017 16:16:35 +0100 Subject: [PATCH] Refactor: Keep information about OpenLDAP constants in Python, generate C Modules/errors.{c,h} are merged into Modules/constants.{c,h} The function LDAPerror_TypeError is moved to common.{c,h}, as it's not concerned with LDAPError. Add a new Python module, ldap.constants, to keep information about all OpenLDAP constants that we know about, including those that aren't available in the OpenLDAP used. Generate a C header file, Modules/constants_generated.h, from this information. (Checking generated files into Git is better avoided, but it's much more straightforward than generating the file from setup.py.) Use proper error checking when adding the constants. --- Lib/ldap/constants.py | 402 +++++++++++++++++++++++++++++ Modules/LDAPObject.c | 1 - Modules/common.c | 12 + Modules/common.h | 2 + Modules/constants.c | 470 +++++++++++----------------------- Modules/constants.h | 9 +- Modules/constants_generated.h | 366 ++++++++++++++++++++++++++ Modules/errors.c | 249 ------------------ Modules/errors.h | 16 -- Modules/functions.c | 2 +- Modules/ldapcontrol.c | 1 - Modules/ldapmodule.c | 7 +- Modules/message.c | 1 - Modules/options.c | 2 +- setup.py | 1 - 15 files changed, 950 insertions(+), 591 deletions(-) create mode 100644 Lib/ldap/constants.py create mode 100644 Modules/constants_generated.h delete mode 100644 Modules/errors.c delete mode 100644 Modules/errors.h diff --git a/Lib/ldap/constants.py b/Lib/ldap/constants.py new file mode 100644 index 0000000..6469a30 --- /dev/null +++ b/Lib/ldap/constants.py @@ -0,0 +1,402 @@ +"""Definitions for constants exported by OpenLDAP + +This file lists all constants we know about, even those that aren't +available in the OpenLDAP version python-ldap is compiled against. + +The information serves two purposes: + +- Generate a C header with the constants +- Provide support for building documentation without compiling python-ldap + +""" + +from __future__ import print_function + +class Constant(object): + """Base class for a definition of an OpenLDAP constant + """ + + def __init__(self, name, optional=False, requirements=(), doc=None): + self.name = name + if optional: + self_requirement = 'defined(LDAP_{})'.format(self.name) + requirements = list(requirements) + [self_requirement] + self.requirements = requirements + self.doc = self.__doc__ = doc + + +class Error(Constant): + """Definition for an OpenLDAP error code + + This is a constant at the C level; in Python errors are provided as + exception classes. + """ + + c_template = 'add_err({self.name});' + + +class Int(Constant): + """Definition for an OpenLDAP integer constant""" + + c_template = 'add_int({self.name});' + + +class TLSInt(Int): + """Definition for a TLS integer constant -- requires HAVE_TLS""" + + def __init__(self, *args, **kwargs): + requrements = list(kwargs.get('requirements', ())) + kwargs['requirements'] = ['HAVE_TLS'] + requrements + super(TLSInt, self).__init__(*args, **kwargs) + + +class Feature(Constant): + """Definition for a feature: 0 or 1 based on a C #ifdef + + """ + + c_template = '\n'.join([ + '', + '#ifdef {self.c_feature}', + 'result = PyModule_AddIntConstant(m, "{self.name}", 1);', + '#else', + 'result = PyModule_AddIntConstant(m, "{self.name}", 0);', + '#endif', + 'check_result();', + '', + ]) + + + def __init__(self, name, c_feature, **kwargs): + super(Feature, self).__init__(name, **kwargs) + self.c_feature = c_feature + + +class Str(Constant): + c_template = 'add_string({self.name});' + + +API_2004 = 'LDAP_API_VERSION >= 2004' + +CONSTANTS = ( + Error('ADMINLIMIT_EXCEEDED'), + Error('AFFECTS_MULTIPLE_DSAS'), + Error('ALIAS_DEREF_PROBLEM'), + Error('ALIAS_PROBLEM'), + Error('ALREADY_EXISTS'), + Error('AUTH_METHOD_NOT_SUPPORTED'), + Error('AUTH_UNKNOWN'), + Error('BUSY'), + Error('CLIENT_LOOP'), + Error('COMPARE_FALSE'), + Error('COMPARE_TRUE'), + Error('CONFIDENTIALITY_REQUIRED'), + Error('CONNECT_ERROR'), + Error('CONSTRAINT_VIOLATION'), + Error('CONTROL_NOT_FOUND'), + Error('DECODING_ERROR'), + Error('ENCODING_ERROR'), + Error('FILTER_ERROR'), + Error('INAPPROPRIATE_AUTH'), + Error('INAPPROPRIATE_MATCHING'), + Error('INSUFFICIENT_ACCESS'), + Error('INVALID_CREDENTIALS'), + Error('INVALID_DN_SYNTAX'), + Error('INVALID_SYNTAX'), + Error('IS_LEAF'), + Error('LOCAL_ERROR'), + Error('LOOP_DETECT'), + Error('MORE_RESULTS_TO_RETURN'), + Error('NAMING_VIOLATION'), + Error('NO_MEMORY'), + Error('NO_OBJECT_CLASS_MODS'), + Error('NO_OBJECT_CLASS_MODS'), + Error('NO_RESULTS_RETURNED'), + Error('NO_SUCH_ATTRIBUTE'), + Error('NO_SUCH_OBJECT'), + Error('NOT_ALLOWED_ON_NONLEAF'), + Error('NOT_ALLOWED_ON_RDN'), + Error('NOT_SUPPORTED'), + Error('OBJECT_CLASS_VIOLATION'), + Error('OPERATIONS_ERROR'), + Error('OTHER'), + Error('PARAM_ERROR'), + Error('PARTIAL_RESULTS'), + Error('PROTOCOL_ERROR'), + Error('REFERRAL'), + Error('REFERRAL_LIMIT_EXCEEDED'), + Error('RESULTS_TOO_LARGE'), + Error('SASL_BIND_IN_PROGRESS'), + Error('SERVER_DOWN'), + Error('SIZELIMIT_EXCEEDED'), + Error('STRONG_AUTH_NOT_SUPPORTED'), + Error('STRONG_AUTH_REQUIRED'), + Error('SUCCESS'), + Error('TIMELIMIT_EXCEEDED'), + Error('TIMEOUT'), + Error('TYPE_OR_VALUE_EXISTS'), + Error('UNAVAILABLE'), + Error('UNAVAILABLE_CRITICAL_EXTENSION'), + Error('UNDEFINED_TYPE'), + Error('UNWILLING_TO_PERFORM'), + Error('USER_CANCELLED'), + Error('VLV_ERROR'), + Error('X_PROXY_AUTHZ_FAILURE'), + + Error('CANCELLED', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('NO_SUCH_OPERATION', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('TOO_LATE', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('CANNOT_CANCEL', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + + Error('ASSERTION_FAILED', optional=True), + + Error('PROXIED_AUTHORIZATION_DENIED', optional=True), + + # simple constants + + Int('API_VERSION'), + Int('VENDOR_VERSION'), + + Int('PORT'), + Int('VERSION1'), + Int('VERSION2'), + Int('VERSION3'), + Int('VERSION_MIN'), + Int('VERSION'), + Int('VERSION_MAX'), + Int('TAG_MESSAGE'), + Int('TAG_MSGID'), + + Int('REQ_BIND'), + Int('REQ_UNBIND'), + Int('REQ_SEARCH'), + Int('REQ_MODIFY'), + Int('REQ_ADD'), + Int('REQ_DELETE'), + Int('REQ_MODRDN'), + Int('REQ_COMPARE'), + Int('REQ_ABANDON'), + + Int('TAG_LDAPDN'), + Int('TAG_LDAPCRED'), + Int('TAG_CONTROLS'), + Int('TAG_REFERRAL'), + + Int('REQ_EXTENDED'), + Int('TAG_NEWSUPERIOR', requirements=[API_2004]), + Int('TAG_EXOP_REQ_OID', requirements=[API_2004]), + Int('TAG_EXOP_REQ_VALUE', requirements=[API_2004]), + Int('TAG_EXOP_RES_OID', requirements=[API_2004]), + Int('TAG_EXOP_RES_VALUE', requirements=[API_2004]), + Int('TAG_SASL_RES_CREDS', requirements=[API_2004, 'defined(HAVE_SASL)']), + + Int('SASL_AUTOMATIC'), + Int('SASL_INTERACTIVE'), + Int('SASL_QUIET'), + + # reversibles + + Int('RES_BIND'), + Int('RES_SEARCH_ENTRY'), + Int('RES_SEARCH_RESULT'), + Int('RES_MODIFY'), + Int('RES_ADD'), + Int('RES_DELETE'), + Int('RES_MODRDN'), + Int('RES_COMPARE'), + Int('RES_ANY'), + + Int('RES_SEARCH_REFERENCE'), + Int('RES_EXTENDED'), + Int('RES_UNSOLICITED'), + + Int('RES_INTERMEDIATE'), + + # non-reversibles + + Int('AUTH_NONE'), + Int('AUTH_SIMPLE'), + Int('SCOPE_BASE'), + Int('SCOPE_ONELEVEL'), + Int('SCOPE_SUBTREE'), + Int('SCOPE_SUBORDINATE', optional=True), + Int('MOD_ADD'), + Int('MOD_DELETE'), + Int('MOD_REPLACE'), + Int('MOD_INCREMENT'), + Int('MOD_BVALUES'), + + Int('MSG_ONE'), + Int('MSG_ALL'), + Int('MSG_RECEIVED'), + + # (error constants handled above) + + Int('DEREF_NEVER'), + Int('DEREF_SEARCHING'), + Int('DEREF_FINDING'), + Int('DEREF_ALWAYS'), + Int('NO_LIMIT'), + + Int('OPT_API_INFO'), + Int('OPT_DEREF'), + Int('OPT_SIZELIMIT'), + Int('OPT_TIMELIMIT'), + Int('OPT_REFERRALS', optional=True), + Int('OPT_ERROR_NUMBER'), + Int('OPT_RESTART'), + Int('OPT_PROTOCOL_VERSION'), + Int('OPT_SERVER_CONTROLS'), + Int('OPT_CLIENT_CONTROLS'), + Int('OPT_API_FEATURE_INFO'), + Int('OPT_HOST_NAME'), + + Int('OPT_DESC'), + Int('OPT_DIAGNOSTIC_MESSAGE'), + + Int('OPT_ERROR_STRING'), + Int('OPT_MATCHED_DN'), + Int('OPT_DEBUG_LEVEL'), + Int('OPT_TIMEOUT'), + Int('OPT_REFHOPLIMIT'), + Int('OPT_NETWORK_TIMEOUT'), + Int('OPT_URI'), + + Int('OPT_DEFBASE', optional=True), + + TLSInt('OPT_X_TLS', optional=True), + TLSInt('OPT_X_TLS_CTX'), + TLSInt('OPT_X_TLS_CACERTFILE'), + TLSInt('OPT_X_TLS_CACERTDIR'), + TLSInt('OPT_X_TLS_CERTFILE'), + TLSInt('OPT_X_TLS_KEYFILE'), + TLSInt('OPT_X_TLS_REQUIRE_CERT'), + TLSInt('OPT_X_TLS_CIPHER_SUITE'), + TLSInt('OPT_X_TLS_RANDOM_FILE'), + TLSInt('OPT_X_TLS_DHFILE'), + TLSInt('OPT_X_TLS_NEVER'), + TLSInt('OPT_X_TLS_HARD'), + TLSInt('OPT_X_TLS_DEMAND'), + TLSInt('OPT_X_TLS_ALLOW'), + TLSInt('OPT_X_TLS_TRY'), + TLSInt('OPT_X_TLS_PEERCERT', optional=True), + + TLSInt('OPT_X_TLS_VERSION', optional=True), + TLSInt('OPT_X_TLS_CIPHER', optional=True), + TLSInt('OPT_X_TLS_PEERCERT', optional=True), + + # only available if OpenSSL supports it => might cause + # backward compability problems + TLSInt('OPT_X_TLS_CRLCHECK', optional=True), + + TLSInt('OPT_X_TLS_CRLFILE', optional=True), + + TLSInt('OPT_X_TLS_CRL_NONE'), + TLSInt('OPT_X_TLS_CRL_PEER'), + TLSInt('OPT_X_TLS_CRL_ALL'), + TLSInt('OPT_X_TLS_NEWCTX', optional=True), + TLSInt('OPT_X_TLS_PROTOCOL_MIN', optional=True), + TLSInt('OPT_X_TLS_PACKAGE', optional=True), + + Int('OPT_X_SASL_MECH'), + Int('OPT_X_SASL_REALM'), + Int('OPT_X_SASL_AUTHCID'), + Int('OPT_X_SASL_AUTHZID'), + Int('OPT_X_SASL_SSF'), + Int('OPT_X_SASL_SSF_EXTERNAL'), + Int('OPT_X_SASL_SECPROPS'), + Int('OPT_X_SASL_SSF_MIN'), + Int('OPT_X_SASL_SSF_MAX'), + Int('OPT_X_SASL_NOCANON', optional=True), + Int('OPT_X_SASL_USERNAME', optional=True), + Int('OPT_CONNECT_ASYNC', optional=True), + Int('OPT_X_KEEPALIVE_IDLE', optional=True), + Int('OPT_X_KEEPALIVE_PROBES', optional=True), + Int('OPT_X_KEEPALIVE_INTERVAL', optional=True), + + Int('DN_FORMAT_LDAP'), + Int('DN_FORMAT_LDAPV3'), + Int('DN_FORMAT_LDAPV2'), + Int('DN_FORMAT_DCE'), + Int('DN_FORMAT_UFN'), + Int('DN_FORMAT_AD_CANONICAL'), + # Int('DN_FORMAT_LBER'), # for testing only + Int('DN_FORMAT_MASK'), + Int('DN_PRETTY'), + Int('DN_SKIP'), + Int('DN_P_NOLEADTRAILSPACES'), + Int('DN_P_NOSPACEAFTERRDN'), + Int('DN_PEDANTIC'), + + Int('AVA_NULL'), + Int('AVA_STRING'), + Int('AVA_BINARY'), + Int('AVA_NONPRINTABLE'), + + Int('OPT_SUCCESS'), + + # XXX - these should be errors + Int('URL_ERR_BADSCOPE'), + Int('URL_ERR_MEM'), + # Int('LIBLDAP_R'), + + Feature('LIBLDAP_R', 'HAVE_LIBLDAP_R'), + Feature('SASL_AVAIL', 'HAVE_SASL'), + Feature('TLS_AVAIL', 'HAVE_TLS'), + + Str("CONTROL_MANAGEDSAIT"), + Str("CONTROL_PROXY_AUTHZ"), + Str("CONTROL_SUBENTRIES"), + Str("CONTROL_VALUESRETURNFILTER"), + Str("CONTROL_ASSERT"), + Str("CONTROL_PRE_READ"), + Str("CONTROL_POST_READ"), + Str("CONTROL_SORTREQUEST"), + Str("CONTROL_SORTRESPONSE"), + Str("CONTROL_PAGEDRESULTS"), + Str("CONTROL_SYNC"), + Str("CONTROL_SYNC_STATE"), + Str("CONTROL_SYNC_DONE"), + Str("SYNC_INFO"), + Str("CONTROL_PASSWORDPOLICYREQUEST"), + Str("CONTROL_PASSWORDPOLICYRESPONSE"), + Str("CONTROL_RELAX"), +) + + +def print_header(): + """Print the C header file to standard output""" + + print('/*') + print(' * Generated with:') + print(' * python Lib/ldap/constants.py > Modules/constants_generated.h') + print(' *') + print(' * Please do any modifications there, then re-generate this file') + print(' */') + print('') + + current_requirements = [] + + def pop_requirement(): + popped = current_requirements.pop() + print('#endif') + print() + + for definition in CONSTANTS: + while not set(current_requirements).issubset(definition.requirements): + pop_requirement() + + for requirement in definition.requirements: + if requirement not in current_requirements: + current_requirements.append(requirement) + print() + print('#if {}'.format(requirement)) + + print(definition.c_template.format(self=definition)) + + while current_requirements: + pop_requirement() + + +if __name__ == '__main__': + print_header() diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index a434986..f1ad0d4 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -5,7 +5,6 @@ #include #include -#include "errors.h" #include "constants.h" #include "LDAPObject.h" #include "ldapcontrol.h" diff --git a/Modules/common.c b/Modules/common.c index 7d3ac8b..0f0cd36 100644 --- a/Modules/common.c +++ b/Modules/common.c @@ -16,3 +16,15 @@ LDAPadd_methods( PyObject* d, PyMethodDef* methods ) Py_DECREF(f); } } + +/* Raise TypeError with custom message and object */ +PyObject* +LDAPerror_TypeError(const char *msg, PyObject *obj) { + PyObject *args = Py_BuildValue("sO", msg, obj); + if (args == NULL) { + return NULL; + } + PyErr_SetObject(PyExc_TypeError, args); + Py_DECREF(args); + return NULL; +} diff --git a/Modules/common.h b/Modules/common.h index 0eea1d9..029f234 100644 --- a/Modules/common.h +++ b/Modules/common.h @@ -24,6 +24,8 @@ #define streq( a, b ) \ ( (*(a)==*(b)) && 0==strcmp(a,b) ) +extern PyObject* LDAPerror_TypeError(const char *, PyObject *); + void LDAPadd_methods( PyObject*d, PyMethodDef*methods ); #define PyNone_Check(o) ((o) == Py_None) diff --git a/Modules/constants.c b/Modules/constants.c index cd3877c..4fd09b8 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -6,346 +6,184 @@ #include "lber.h" #include "ldap.h" -/* initialise the module constants */ - -void -LDAPinit_constants( PyObject* d ) -{ - PyObject *obj; +/* the base exception class */ -#define add_int(d, name) \ - { \ - PyObject *i = PyInt_FromLong(LDAP_##name); \ - PyDict_SetItemString( d, #name, i ); \ - Py_DECREF(i); \ - } +PyObject* +LDAPexception_class; - /* simple constants */ - - add_int(d,API_VERSION); - add_int(d,VENDOR_VERSION); - - add_int(d,PORT); - add_int(d,VERSION1); - add_int(d,VERSION2); - add_int(d,VERSION3); - add_int(d,VERSION_MIN); - add_int(d,VERSION); - add_int(d,VERSION_MAX); - add_int(d,TAG_MESSAGE); - add_int(d,TAG_MSGID); - - add_int(d,REQ_BIND); - add_int(d,REQ_UNBIND); - add_int(d,REQ_SEARCH); - add_int(d,REQ_MODIFY); - add_int(d,REQ_ADD); - add_int(d,REQ_DELETE); - add_int(d,REQ_MODRDN); - add_int(d,REQ_COMPARE); - add_int(d,REQ_ABANDON); - - add_int(d,TAG_LDAPDN); - add_int(d,TAG_LDAPCRED); - add_int(d,TAG_CONTROLS); - add_int(d,TAG_REFERRAL); - - add_int(d,REQ_EXTENDED); -#if LDAP_API_VERSION >= 2004 - add_int(d,TAG_NEWSUPERIOR); - add_int(d,TAG_EXOP_REQ_OID); - add_int(d,TAG_EXOP_REQ_VALUE); - add_int(d,TAG_EXOP_RES_OID); - add_int(d,TAG_EXOP_RES_VALUE); -#ifdef HAVE_SASL - add_int(d,TAG_SASL_RES_CREDS); -#endif -#endif +/* list of exception classes */ - add_int(d,SASL_AUTOMATIC); - add_int(d,SASL_INTERACTIVE); - add_int(d,SASL_QUIET); - - /* reversibles */ - - add_int(d,RES_BIND); - add_int(d,RES_SEARCH_ENTRY); - add_int(d,RES_SEARCH_RESULT); - add_int(d,RES_MODIFY); - add_int(d,RES_ADD); - add_int(d,RES_DELETE); - add_int(d,RES_MODRDN); - add_int(d,RES_COMPARE); - add_int(d,RES_ANY); - - add_int(d,RES_SEARCH_REFERENCE); - add_int(d,RES_EXTENDED); - add_int(d,RES_UNSOLICITED); - - add_int(d,RES_INTERMEDIATE); - - /* non-reversibles */ - - add_int(d,AUTH_NONE); - add_int(d,AUTH_SIMPLE); - add_int(d,SCOPE_BASE); - add_int(d,SCOPE_ONELEVEL); - add_int(d,SCOPE_SUBTREE); -#ifdef LDAP_SCOPE_SUBORDINATE - add_int(d,SCOPE_SUBORDINATE); -#endif - add_int(d,MOD_ADD); - add_int(d,MOD_DELETE); - add_int(d,MOD_REPLACE); - add_int(d,MOD_INCREMENT); - add_int(d,MOD_BVALUES); - - add_int(d,MSG_ONE); - add_int(d,MSG_ALL); - add_int(d,MSG_RECEIVED); - - /* (errors.c contains the error constants) */ - - add_int(d,DEREF_NEVER); - add_int(d,DEREF_SEARCHING); - add_int(d,DEREF_FINDING); - add_int(d,DEREF_ALWAYS); - add_int(d,NO_LIMIT); - - add_int(d,OPT_API_INFO); - add_int(d,OPT_DEREF); - add_int(d,OPT_SIZELIMIT); - add_int(d,OPT_TIMELIMIT); -#ifdef LDAP_OPT_REFERRALS - add_int(d,OPT_REFERRALS); -#endif - add_int(d,OPT_ERROR_NUMBER); - add_int(d,OPT_RESTART); - add_int(d,OPT_PROTOCOL_VERSION); - add_int(d,OPT_SERVER_CONTROLS); - add_int(d,OPT_CLIENT_CONTROLS); - add_int(d,OPT_API_FEATURE_INFO); - add_int(d,OPT_HOST_NAME); - - add_int(d,OPT_DESC); - add_int(d,OPT_DIAGNOSTIC_MESSAGE); - - add_int(d,OPT_ERROR_STRING); - add_int(d,OPT_MATCHED_DN); - add_int(d,OPT_DEBUG_LEVEL); - add_int(d,OPT_TIMEOUT); - add_int(d,OPT_REFHOPLIMIT); - add_int(d,OPT_NETWORK_TIMEOUT); - add_int(d,OPT_URI); -#ifdef LDAP_OPT_DEFBASE - add_int(d,OPT_DEFBASE); -#endif -#ifdef HAVE_TLS - add_int(d,OPT_X_TLS); -#ifdef LDAP_OPT_X_TLS_NEWCTX - add_int(d,OPT_X_TLS_CTX); -#endif - add_int(d,OPT_X_TLS_CACERTFILE); - add_int(d,OPT_X_TLS_CACERTDIR); - add_int(d,OPT_X_TLS_CERTFILE); - add_int(d,OPT_X_TLS_KEYFILE); - add_int(d,OPT_X_TLS_REQUIRE_CERT); - add_int(d,OPT_X_TLS_CIPHER_SUITE); - add_int(d,OPT_X_TLS_RANDOM_FILE); - add_int(d,OPT_X_TLS_DHFILE); - add_int(d,OPT_X_TLS_NEVER); - add_int(d,OPT_X_TLS_HARD); - add_int(d,OPT_X_TLS_DEMAND); - add_int(d,OPT_X_TLS_ALLOW); - add_int(d,OPT_X_TLS_TRY); -#ifdef LDAP_OPT_X_TLS_PEERCERT - add_int(d,OPT_X_TLS_PEERCERT); -#endif -#ifdef LDAP_OPT_X_TLS_VERSION - add_int(d,OPT_X_TLS_VERSION); -#endif -#ifdef LDAP_OPT_X_TLS_CIPHER - add_int(d,OPT_X_TLS_CIPHER); -#endif -#ifdef LDAP_OPT_X_TLS_PEERCERT - add_int(d,OPT_X_TLS_PEERCERT); -#endif -#ifdef LDAP_OPT_X_TLS_CRLCHECK - /* only available if OpenSSL supports it => might cause backward compability problems */ - add_int(d,OPT_X_TLS_CRLCHECK); -#ifdef LDAP_OPT_X_TLS_CRLFILE - add_int(d,OPT_X_TLS_CRLFILE); -#endif - add_int(d,OPT_X_TLS_CRL_NONE); - add_int(d,OPT_X_TLS_CRL_PEER); - add_int(d,OPT_X_TLS_CRL_ALL); -#endif -#ifdef LDAP_OPT_X_TLS_NEWCTX - add_int(d,OPT_X_TLS_NEWCTX); -#endif -#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN - add_int(d,OPT_X_TLS_PROTOCOL_MIN); -#endif -#ifdef LDAP_OPT_X_TLS_PACKAGE - add_int(d,OPT_X_TLS_PACKAGE); -#endif -#endif - add_int(d,OPT_X_SASL_MECH); - add_int(d,OPT_X_SASL_REALM); - add_int(d,OPT_X_SASL_AUTHCID); - add_int(d,OPT_X_SASL_AUTHZID); - add_int(d,OPT_X_SASL_SSF); - add_int(d,OPT_X_SASL_SSF_EXTERNAL); - add_int(d,OPT_X_SASL_SECPROPS); - add_int(d,OPT_X_SASL_SSF_MIN); - add_int(d,OPT_X_SASL_SSF_MAX); -#ifdef LDAP_OPT_X_SASL_NOCANON - add_int(d,OPT_X_SASL_NOCANON); -#endif -#ifdef LDAP_OPT_X_SASL_USERNAME - add_int(d,OPT_X_SASL_USERNAME); -#endif -#ifdef LDAP_OPT_CONNECT_ASYNC - add_int(d,OPT_CONNECT_ASYNC); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_IDLE - add_int(d,OPT_X_KEEPALIVE_IDLE); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_PROBES - add_int(d,OPT_X_KEEPALIVE_PROBES); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL - add_int(d,OPT_X_KEEPALIVE_INTERVAL); -#endif +#define LDAP_ERROR_MIN LDAP_REFERRAL_LIMIT_EXCEEDED - add_int(d,DN_FORMAT_LDAP); - add_int(d,DN_FORMAT_LDAPV3); - add_int(d,DN_FORMAT_LDAPV2); - add_int(d,DN_FORMAT_DCE); - add_int(d,DN_FORMAT_UFN); - add_int(d,DN_FORMAT_AD_CANONICAL); - /* add_int(d,DN_FORMAT_LBER); */ /* "for testing only" */ - add_int(d,DN_FORMAT_MASK); - add_int(d,DN_PRETTY); - add_int(d,DN_SKIP); - add_int(d,DN_P_NOLEADTRAILSPACES); - add_int(d,DN_P_NOSPACEAFTERRDN); - add_int(d,DN_PEDANTIC); - - add_int(d,AVA_NULL); - add_int(d,AVA_STRING); - add_int(d,AVA_BINARY); - add_int(d,AVA_NONPRINTABLE); - - /*add_int(d,OPT_ON);*/ - obj = PyInt_FromLong(1); - PyDict_SetItemString( d, "OPT_ON", obj ); - Py_DECREF(obj); - /*add_int(d,OPT_OFF);*/ - obj = PyInt_FromLong(0); - PyDict_SetItemString( d, "OPT_OFF", obj ); - Py_DECREF(obj); - - add_int(d,OPT_SUCCESS); - - /* XXX - these belong in errors.c */ - - add_int(d,URL_ERR_BADSCOPE); - add_int(d,URL_ERR_MEM); - - /* add_int(d,LIBLDAP_R); */ -#ifdef HAVE_LIBLDAP_R - obj = PyInt_FromLong(1); +#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED + #define LDAP_ERROR_MAX LDAP_PROXIED_AUTHORIZATION_DENIED #else - obj = PyInt_FromLong(0); + #ifdef LDAP_ASSERTION_FAILED + #define LDAP_ERROR_MAX LDAP_ASSERTION_FAILED + #else + #define LDAP_ERROR_MAX LDAP_OTHER + #endif #endif - PyDict_SetItemString( d, "LIBLDAP_R", obj ); - Py_DECREF(obj); - /* add_int(d,SASL); */ -#ifdef HAVE_SASL - obj = PyInt_FromLong(1); -#else - obj = PyInt_FromLong(0); -#endif - PyDict_SetItemString( d, "SASL_AVAIL", obj ); - Py_DECREF(obj); +#define LDAP_ERROR_OFFSET -LDAP_ERROR_MIN + +static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ]; - /* add_int(d,TLS); */ -#ifdef HAVE_TLS - obj = PyInt_FromLong(1); -#else - obj = PyInt_FromLong(0); -#endif - PyDict_SetItemString( d, "TLS_AVAIL", obj ); - Py_DECREF(obj); - obj = PyUnicode_FromString(LDAP_CONTROL_MANAGEDSAIT); - PyDict_SetItemString( d, "CONTROL_MANAGEDSAIT", obj ); - Py_DECREF(obj); +/* Convert a bare LDAP error number into an exception */ +PyObject* +LDAPerr(int errnum) +{ + if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) { + PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]); + } else { + PyObject *args = Py_BuildValue("{s:i}", "errnum", errnum); + if (args == NULL) + return NULL; + PyErr_SetObject(LDAPexception_class, args); + Py_DECREF(args); + } + return NULL; +} - obj = PyUnicode_FromString(LDAP_CONTROL_PROXY_AUTHZ); - PyDict_SetItemString( d, "CONTROL_PROXY_AUTHZ", obj ); - Py_DECREF(obj); +/* Convert an LDAP error into an informative python exception */ +PyObject* +LDAPerror( LDAP *l, char *msg ) +{ + if (l == NULL) { + PyErr_SetFromErrno( LDAPexception_class ); + return NULL; + } + else { + int myerrno, errnum, opt_errnum; + PyObject *errobj; + PyObject *info; + PyObject *str; + PyObject *pyerrno; + + /* at first save errno for later use before it gets overwritten by another call */ + myerrno = errno; + + char *matched, *error; + + opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum); + if (opt_errnum != LDAP_OPT_SUCCESS) + errnum = opt_errnum; + + if (errnum == LDAP_NO_MEMORY) + return PyErr_NoMemory(); + + if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) + errobj = errobjects[errnum+LDAP_ERROR_OFFSET]; + else + errobj = LDAPexception_class; + + info = PyDict_New(); + if (info == NULL) + return NULL; + + str = PyUnicode_FromString(ldap_err2string(errnum)); + if (str) + PyDict_SetItemString( info, "desc", str ); + Py_XDECREF(str); + + if (myerrno != 0) { + pyerrno = PyInt_FromLong(myerrno); + if (pyerrno) + PyDict_SetItemString( info, "errno", pyerrno ); + Py_XDECREF(pyerrno); + } + + if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0 + && matched != NULL) { + if (*matched != '\0') { + str = PyUnicode_FromString(matched); + if (str) + PyDict_SetItemString( info, "matched", str ); + Py_XDECREF(str); + } + ldap_memfree(matched); + } + + if (errnum == LDAP_REFERRAL) { + str = PyUnicode_FromString(msg); + if (str) + PyDict_SetItemString( info, "info", str ); + Py_XDECREF(str); + } else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) { + if (error != NULL && *error != '\0') { + str = PyUnicode_FromString(error); + if (str) + PyDict_SetItemString( info, "info", str ); + Py_XDECREF(str); + } + ldap_memfree(error); + } + PyErr_SetObject( errobj, info ); + Py_DECREF(info); + return NULL; + } +} - obj = PyUnicode_FromString(LDAP_CONTROL_SUBENTRIES); - PyDict_SetItemString( d, "CONTROL_SUBENTRIES", obj ); - Py_DECREF(obj); +/* initialise the module constants */ - obj = PyUnicode_FromString(LDAP_CONTROL_VALUESRETURNFILTER); - PyDict_SetItemString( d, "CONTROL_VALUESRETURNFILTER", obj ); - Py_DECREF(obj); +int +LDAPinit_constants( PyObject* m ) +{ + PyObject *exc; + int result; - obj = PyUnicode_FromString(LDAP_CONTROL_ASSERT); - PyDict_SetItemString( d, "CONTROL_ASSERT", obj ); - Py_DECREF(obj); +#define check_result() { \ + if (result != 0) return -1; \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PRE_READ); - PyDict_SetItemString( d, "CONTROL_PRE_READ", obj ); - Py_DECREF(obj); + /* simple constants */ - obj = PyUnicode_FromString(LDAP_CONTROL_POST_READ); - PyDict_SetItemString( d, "CONTROL_POST_READ", obj ); - Py_DECREF(obj); + result = PyModule_AddIntConstant(m, "OPT_ON", 1); + check_result(); + result = PyModule_AddIntConstant(m, "OPT_OFF", 0); + check_result(); - obj = PyUnicode_FromString(LDAP_CONTROL_SORTREQUEST); - PyDict_SetItemString( d, "CONTROL_SORTREQUEST", obj ); - Py_DECREF(obj); + /* exceptions */ - obj = PyUnicode_FromString(LDAP_CONTROL_SORTRESPONSE); - PyDict_SetItemString( d, "CONTROL_SORTRESPONSE", obj ); - Py_DECREF(obj); + LDAPexception_class = PyErr_NewException("ldap.LDAPError", NULL, NULL); + if (LDAPexception_class == NULL) { + return -1; + } - obj = PyUnicode_FromString(LDAP_CONTROL_PAGEDRESULTS); - PyDict_SetItemString( d, "CONTROL_PAGEDRESULTS", obj ); - Py_DECREF(obj); + result = PyModule_AddObject(m, "LDAPError", LDAPexception_class); + check_result(); + Py_INCREF(LDAPexception_class); - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC); - PyDict_SetItemString( d, "CONTROL_SYNC", obj ); - Py_DECREF(obj); + /* XXX - backward compatibility with pre-1.8 */ + result = PyModule_AddObject(m, "error", LDAPexception_class); + check_result(); + Py_INCREF(LDAPexception_class); - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC_STATE); - PyDict_SetItemString( d, "CONTROL_SYNC_STATE", obj ); - Py_DECREF(obj); + /* Generated constants -- see Lib/ldap/constants.py */ - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC_DONE); - PyDict_SetItemString( d, "CONTROL_SYNC_DONE", obj ); - Py_DECREF(obj); +#define seterrobj2(n, o) \ + PyModule_AddObject(m, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o)) - obj = PyUnicode_FromString(LDAP_SYNC_INFO); - PyDict_SetItemString( d, "SYNC_INFO", obj ); - Py_DECREF(obj); +#define add_err(n) { \ + exc = PyErr_NewException("ldap." #n, LDAPexception_class, NULL); \ + if (exc == NULL) return -1; \ + result = seterrobj2(n, exc); \ + check_result(); \ + Py_INCREF(exc); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PASSWORDPOLICYREQUEST); - PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYREQUEST", obj ); - Py_DECREF(obj); +#define add_int(n) { \ + result = PyModule_AddIntConstant(m, #n, LDAP_##n); \ + check_result(); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PASSWORDPOLICYRESPONSE); - PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYRESPONSE", obj ); - Py_DECREF(obj); +#define add_string(n) { \ + result = PyModule_AddStringConstant(m, #n, LDAP_##n); \ + check_result(); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_RELAX); - PyDict_SetItemString( d, "CONTROL_RELAX", obj ); - Py_DECREF(obj); +#include "constants_generated.h" + return 0; } diff --git a/Modules/constants.h b/Modules/constants.h index eb76612..4056f90 100644 --- a/Modules/constants.h +++ b/Modules/constants.h @@ -4,9 +4,16 @@ #define __h_constants_ #include "common.h" -extern void LDAPinit_constants( PyObject* d ); +#include "lber.h" +#include "ldap.h" + +extern int LDAPinit_constants( PyObject* m ); extern PyObject* LDAPconstant( int ); +extern PyObject* LDAPexception_class; +extern PyObject* LDAPerror( LDAP*, char*msg ); +PyObject* LDAPerr(int errnum); + #ifndef LDAP_CONTROL_PAGE_OID #define LDAP_CONTROL_PAGE_OID "1.2.840.113556.1.4.319" #endif /* !LDAP_CONTROL_PAGE_OID */ diff --git a/Modules/constants_generated.h b/Modules/constants_generated.h new file mode 100644 index 0000000..27addc9 --- /dev/null +++ b/Modules/constants_generated.h @@ -0,0 +1,366 @@ +/* + * Generated with: + * python Lib/ldap/constants.py > Modules/constants_generated.h + * + * Please do any modifications there, then re-generate this file + */ + +add_err(ADMINLIMIT_EXCEEDED); +add_err(AFFECTS_MULTIPLE_DSAS); +add_err(ALIAS_DEREF_PROBLEM); +add_err(ALIAS_PROBLEM); +add_err(ALREADY_EXISTS); +add_err(AUTH_METHOD_NOT_SUPPORTED); +add_err(AUTH_UNKNOWN); +add_err(BUSY); +add_err(CLIENT_LOOP); +add_err(COMPARE_FALSE); +add_err(COMPARE_TRUE); +add_err(CONFIDENTIALITY_REQUIRED); +add_err(CONNECT_ERROR); +add_err(CONSTRAINT_VIOLATION); +add_err(CONTROL_NOT_FOUND); +add_err(DECODING_ERROR); +add_err(ENCODING_ERROR); +add_err(FILTER_ERROR); +add_err(INAPPROPRIATE_AUTH); +add_err(INAPPROPRIATE_MATCHING); +add_err(INSUFFICIENT_ACCESS); +add_err(INVALID_CREDENTIALS); +add_err(INVALID_DN_SYNTAX); +add_err(INVALID_SYNTAX); +add_err(IS_LEAF); +add_err(LOCAL_ERROR); +add_err(LOOP_DETECT); +add_err(MORE_RESULTS_TO_RETURN); +add_err(NAMING_VIOLATION); +add_err(NO_MEMORY); +add_err(NO_OBJECT_CLASS_MODS); +add_err(NO_OBJECT_CLASS_MODS); +add_err(NO_RESULTS_RETURNED); +add_err(NO_SUCH_ATTRIBUTE); +add_err(NO_SUCH_OBJECT); +add_err(NOT_ALLOWED_ON_NONLEAF); +add_err(NOT_ALLOWED_ON_RDN); +add_err(NOT_SUPPORTED); +add_err(OBJECT_CLASS_VIOLATION); +add_err(OPERATIONS_ERROR); +add_err(OTHER); +add_err(PARAM_ERROR); +add_err(PARTIAL_RESULTS); +add_err(PROTOCOL_ERROR); +add_err(REFERRAL); +add_err(REFERRAL_LIMIT_EXCEEDED); +add_err(RESULTS_TOO_LARGE); +add_err(SASL_BIND_IN_PROGRESS); +add_err(SERVER_DOWN); +add_err(SIZELIMIT_EXCEEDED); +add_err(STRONG_AUTH_NOT_SUPPORTED); +add_err(STRONG_AUTH_REQUIRED); +add_err(SUCCESS); +add_err(TIMELIMIT_EXCEEDED); +add_err(TIMEOUT); +add_err(TYPE_OR_VALUE_EXISTS); +add_err(UNAVAILABLE); +add_err(UNAVAILABLE_CRITICAL_EXTENSION); +add_err(UNDEFINED_TYPE); +add_err(UNWILLING_TO_PERFORM); +add_err(USER_CANCELLED); +add_err(VLV_ERROR); +add_err(X_PROXY_AUTHZ_FAILURE); + +#if defined(LDAP_API_FEATURE_CANCEL) +add_err(CANCELLED); +add_err(NO_SUCH_OPERATION); +add_err(TOO_LATE); +add_err(CANNOT_CANCEL); +#endif + + +#if defined(LDAP_ASSERTION_FAILED) +add_err(ASSERTION_FAILED); +#endif + + +#if defined(LDAP_PROXIED_AUTHORIZATION_DENIED) +add_err(PROXIED_AUTHORIZATION_DENIED); +#endif + +add_int(API_VERSION); +add_int(VENDOR_VERSION); +add_int(PORT); +add_int(VERSION1); +add_int(VERSION2); +add_int(VERSION3); +add_int(VERSION_MIN); +add_int(VERSION); +add_int(VERSION_MAX); +add_int(TAG_MESSAGE); +add_int(TAG_MSGID); +add_int(REQ_BIND); +add_int(REQ_UNBIND); +add_int(REQ_SEARCH); +add_int(REQ_MODIFY); +add_int(REQ_ADD); +add_int(REQ_DELETE); +add_int(REQ_MODRDN); +add_int(REQ_COMPARE); +add_int(REQ_ABANDON); +add_int(TAG_LDAPDN); +add_int(TAG_LDAPCRED); +add_int(TAG_CONTROLS); +add_int(TAG_REFERRAL); +add_int(REQ_EXTENDED); + +#if LDAP_API_VERSION >= 2004 +add_int(TAG_NEWSUPERIOR); +add_int(TAG_EXOP_REQ_OID); +add_int(TAG_EXOP_REQ_VALUE); +add_int(TAG_EXOP_RES_OID); +add_int(TAG_EXOP_RES_VALUE); + +#if defined(HAVE_SASL) +add_int(TAG_SASL_RES_CREDS); +#endif + +#endif + +add_int(SASL_AUTOMATIC); +add_int(SASL_INTERACTIVE); +add_int(SASL_QUIET); +add_int(RES_BIND); +add_int(RES_SEARCH_ENTRY); +add_int(RES_SEARCH_RESULT); +add_int(RES_MODIFY); +add_int(RES_ADD); +add_int(RES_DELETE); +add_int(RES_MODRDN); +add_int(RES_COMPARE); +add_int(RES_ANY); +add_int(RES_SEARCH_REFERENCE); +add_int(RES_EXTENDED); +add_int(RES_UNSOLICITED); +add_int(RES_INTERMEDIATE); +add_int(AUTH_NONE); +add_int(AUTH_SIMPLE); +add_int(SCOPE_BASE); +add_int(SCOPE_ONELEVEL); +add_int(SCOPE_SUBTREE); + +#if defined(LDAP_SCOPE_SUBORDINATE) +add_int(SCOPE_SUBORDINATE); +#endif + +add_int(MOD_ADD); +add_int(MOD_DELETE); +add_int(MOD_REPLACE); +add_int(MOD_INCREMENT); +add_int(MOD_BVALUES); +add_int(MSG_ONE); +add_int(MSG_ALL); +add_int(MSG_RECEIVED); +add_int(DEREF_NEVER); +add_int(DEREF_SEARCHING); +add_int(DEREF_FINDING); +add_int(DEREF_ALWAYS); +add_int(NO_LIMIT); +add_int(OPT_API_INFO); +add_int(OPT_DEREF); +add_int(OPT_SIZELIMIT); +add_int(OPT_TIMELIMIT); + +#if defined(LDAP_OPT_REFERRALS) +add_int(OPT_REFERRALS); +#endif + +add_int(OPT_ERROR_NUMBER); +add_int(OPT_RESTART); +add_int(OPT_PROTOCOL_VERSION); +add_int(OPT_SERVER_CONTROLS); +add_int(OPT_CLIENT_CONTROLS); +add_int(OPT_API_FEATURE_INFO); +add_int(OPT_HOST_NAME); +add_int(OPT_DESC); +add_int(OPT_DIAGNOSTIC_MESSAGE); +add_int(OPT_ERROR_STRING); +add_int(OPT_MATCHED_DN); +add_int(OPT_DEBUG_LEVEL); +add_int(OPT_TIMEOUT); +add_int(OPT_REFHOPLIMIT); +add_int(OPT_NETWORK_TIMEOUT); +add_int(OPT_URI); + +#if defined(LDAP_OPT_DEFBASE) +add_int(OPT_DEFBASE); +#endif + + +#if HAVE_TLS + +#if defined(LDAP_OPT_X_TLS) +add_int(OPT_X_TLS); +#endif + +add_int(OPT_X_TLS_CTX); +add_int(OPT_X_TLS_CACERTFILE); +add_int(OPT_X_TLS_CACERTDIR); +add_int(OPT_X_TLS_CERTFILE); +add_int(OPT_X_TLS_KEYFILE); +add_int(OPT_X_TLS_REQUIRE_CERT); +add_int(OPT_X_TLS_CIPHER_SUITE); +add_int(OPT_X_TLS_RANDOM_FILE); +add_int(OPT_X_TLS_DHFILE); +add_int(OPT_X_TLS_NEVER); +add_int(OPT_X_TLS_HARD); +add_int(OPT_X_TLS_DEMAND); +add_int(OPT_X_TLS_ALLOW); +add_int(OPT_X_TLS_TRY); + +#if defined(LDAP_OPT_X_TLS_PEERCERT) +add_int(OPT_X_TLS_PEERCERT); +#endif + + +#if defined(LDAP_OPT_X_TLS_VERSION) +add_int(OPT_X_TLS_VERSION); +#endif + + +#if defined(LDAP_OPT_X_TLS_CIPHER) +add_int(OPT_X_TLS_CIPHER); +#endif + + +#if defined(LDAP_OPT_X_TLS_PEERCERT) +add_int(OPT_X_TLS_PEERCERT); +#endif + + +#if defined(LDAP_OPT_X_TLS_CRLCHECK) +add_int(OPT_X_TLS_CRLCHECK); +#endif + + +#if defined(LDAP_OPT_X_TLS_CRLFILE) +add_int(OPT_X_TLS_CRLFILE); +#endif + +add_int(OPT_X_TLS_CRL_NONE); +add_int(OPT_X_TLS_CRL_PEER); +add_int(OPT_X_TLS_CRL_ALL); + +#if defined(LDAP_OPT_X_TLS_NEWCTX) +add_int(OPT_X_TLS_NEWCTX); +#endif + + +#if defined(LDAP_OPT_X_TLS_PROTOCOL_MIN) +add_int(OPT_X_TLS_PROTOCOL_MIN); +#endif + + +#if defined(LDAP_OPT_X_TLS_PACKAGE) +add_int(OPT_X_TLS_PACKAGE); +#endif + +#endif + +add_int(OPT_X_SASL_MECH); +add_int(OPT_X_SASL_REALM); +add_int(OPT_X_SASL_AUTHCID); +add_int(OPT_X_SASL_AUTHZID); +add_int(OPT_X_SASL_SSF); +add_int(OPT_X_SASL_SSF_EXTERNAL); +add_int(OPT_X_SASL_SECPROPS); +add_int(OPT_X_SASL_SSF_MIN); +add_int(OPT_X_SASL_SSF_MAX); + +#if defined(LDAP_OPT_X_SASL_NOCANON) +add_int(OPT_X_SASL_NOCANON); +#endif + + +#if defined(LDAP_OPT_X_SASL_USERNAME) +add_int(OPT_X_SASL_USERNAME); +#endif + + +#if defined(LDAP_OPT_CONNECT_ASYNC) +add_int(OPT_CONNECT_ASYNC); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_IDLE) +add_int(OPT_X_KEEPALIVE_IDLE); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_PROBES) +add_int(OPT_X_KEEPALIVE_PROBES); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_INTERVAL) +add_int(OPT_X_KEEPALIVE_INTERVAL); +#endif + +add_int(DN_FORMAT_LDAP); +add_int(DN_FORMAT_LDAPV3); +add_int(DN_FORMAT_LDAPV2); +add_int(DN_FORMAT_DCE); +add_int(DN_FORMAT_UFN); +add_int(DN_FORMAT_AD_CANONICAL); +add_int(DN_FORMAT_MASK); +add_int(DN_PRETTY); +add_int(DN_SKIP); +add_int(DN_P_NOLEADTRAILSPACES); +add_int(DN_P_NOSPACEAFTERRDN); +add_int(DN_PEDANTIC); +add_int(AVA_NULL); +add_int(AVA_STRING); +add_int(AVA_BINARY); +add_int(AVA_NONPRINTABLE); +add_int(OPT_SUCCESS); +add_int(URL_ERR_BADSCOPE); +add_int(URL_ERR_MEM); + +#ifdef HAVE_LIBLDAP_R +result = PyModule_AddIntConstant(m, "LIBLDAP_R", 1); +#else +result = PyModule_AddIntConstant(m, "LIBLDAP_R", 0); +#endif +check_result(); + + +#ifdef HAVE_SASL +result = PyModule_AddIntConstant(m, "SASL_AVAIL", 1); +#else +result = PyModule_AddIntConstant(m, "SASL_AVAIL", 0); +#endif +check_result(); + + +#ifdef HAVE_TLS +result = PyModule_AddIntConstant(m, "TLS_AVAIL", 1); +#else +result = PyModule_AddIntConstant(m, "TLS_AVAIL", 0); +#endif +check_result(); + +add_string(CONTROL_MANAGEDSAIT); +add_string(CONTROL_PROXY_AUTHZ); +add_string(CONTROL_SUBENTRIES); +add_string(CONTROL_VALUESRETURNFILTER); +add_string(CONTROL_ASSERT); +add_string(CONTROL_PRE_READ); +add_string(CONTROL_POST_READ); +add_string(CONTROL_SORTREQUEST); +add_string(CONTROL_SORTRESPONSE); +add_string(CONTROL_PAGEDRESULTS); +add_string(CONTROL_SYNC); +add_string(CONTROL_SYNC_STATE); +add_string(CONTROL_SYNC_DONE); +add_string(SYNC_INFO); +add_string(CONTROL_PASSWORDPOLICYREQUEST); +add_string(CONTROL_PASSWORDPOLICYRESPONSE); +add_string(CONTROL_RELAX); diff --git a/Modules/errors.c b/Modules/errors.c deleted file mode 100644 index 3c4da78..0000000 --- a/Modules/errors.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * errors that arise from ldap use - * Most errors become their own exception - * See https://www.python-ldap.org/ for details. */ - -#include "common.h" -#include "errors.h" -#include -#include - -/* the base exception class */ - -PyObject* -LDAPexception_class; - -/* list of error objects */ - -#define LDAP_ERROR_MIN LDAP_REFERRAL_LIMIT_EXCEEDED - -#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED - #define LDAP_ERROR_MAX LDAP_PROXIED_AUTHORIZATION_DENIED -#else - #ifdef LDAP_ASSERTION_FAILED - #define LDAP_ERROR_MAX LDAP_ASSERTION_FAILED - #else - #define LDAP_ERROR_MAX LDAP_OTHER - #endif -#endif - -#define LDAP_ERROR_OFFSET -LDAP_ERROR_MIN - -static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ]; - - -/* Convert a bare LDAP error number into an exception */ -PyObject* -LDAPerr(int errnum) -{ - if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) { - PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]); - } else { - PyObject *args = Py_BuildValue("{s:i}", "errnum", errnum); - if (args == NULL) - return NULL; - PyErr_SetObject(LDAPexception_class, args); - Py_DECREF(args); - } - return NULL; -} - -/* Convert an LDAP error into an informative python exception */ -PyObject* -LDAPerror( LDAP *l, char *msg ) -{ - if (l == NULL) { - PyErr_SetFromErrno( LDAPexception_class ); - return NULL; - } - else { - int myerrno, errnum, opt_errnum; - PyObject *errobj; - PyObject *info; - PyObject *str; - PyObject *pyerrno; - - /* at first save errno for later use before it gets overwritten by another call */ - myerrno = errno; - - char *matched, *error; - - opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum); - if (opt_errnum != LDAP_OPT_SUCCESS) - errnum = opt_errnum; - - if (errnum == LDAP_NO_MEMORY) - return PyErr_NoMemory(); - - if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) - errobj = errobjects[errnum+LDAP_ERROR_OFFSET]; - else - errobj = LDAPexception_class; - - info = PyDict_New(); - if (info == NULL) - return NULL; - - str = PyUnicode_FromString(ldap_err2string(errnum)); - if (str) - PyDict_SetItemString( info, "desc", str ); - Py_XDECREF(str); - - if (myerrno != 0) { - pyerrno = PyInt_FromLong(myerrno); - if (pyerrno) - PyDict_SetItemString( info, "errno", pyerrno ); - Py_XDECREF(pyerrno); - } - - if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0 - && matched != NULL) { - if (*matched != '\0') { - str = PyUnicode_FromString(matched); - if (str) - PyDict_SetItemString( info, "matched", str ); - Py_XDECREF(str); - } - ldap_memfree(matched); - } - - if (errnum == LDAP_REFERRAL) { - str = PyUnicode_FromString(msg); - if (str) - PyDict_SetItemString( info, "info", str ); - Py_XDECREF(str); - } else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) { - if (error != NULL && *error != '\0') { - str = PyUnicode_FromString(error); - if (str) - PyDict_SetItemString( info, "info", str ); - Py_XDECREF(str); - } - ldap_memfree(error); - } - PyErr_SetObject( errobj, info ); - Py_DECREF(info); - return NULL; - } -} - -/* Raise TypeError with custom message and object */ -PyObject* -LDAPerror_TypeError(const char *msg, PyObject *obj) { - PyObject *args = Py_BuildValue("sO", msg, obj); - if (args == NULL) { - return NULL; - } - PyErr_SetObject(PyExc_TypeError, args); - Py_DECREF(args); - return NULL; -} - - -/* initialisation */ - -void -LDAPinit_errors( PyObject*d ) { - - /* create the base exception class */ - LDAPexception_class = PyErr_NewException("ldap.LDAPError", - NULL, - NULL); - PyDict_SetItemString( d, "LDAPError", LDAPexception_class ); - - /* XXX - backward compatibility with pre-1.8 */ - PyDict_SetItemString( d, "error", LDAPexception_class ); - - /* create each LDAP error object */ - -# define seterrobj2(n,o) \ - PyDict_SetItemString( d, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o) ) - - -# define seterrobj(n) { \ - PyObject *e = PyErr_NewException("ldap." #n, \ - LDAPexception_class, NULL); \ - seterrobj2(n, e); \ - Py_INCREF(e); \ - } - - seterrobj(ADMINLIMIT_EXCEEDED); - seterrobj(AFFECTS_MULTIPLE_DSAS); - seterrobj(ALIAS_DEREF_PROBLEM); - seterrobj(ALIAS_PROBLEM); - seterrobj(ALREADY_EXISTS); - seterrobj(AUTH_METHOD_NOT_SUPPORTED); - seterrobj(AUTH_UNKNOWN); - seterrobj(BUSY); - seterrobj(CLIENT_LOOP); - seterrobj(COMPARE_FALSE); - seterrobj(COMPARE_TRUE); - seterrobj(CONFIDENTIALITY_REQUIRED); - seterrobj(CONNECT_ERROR); - seterrobj(CONSTRAINT_VIOLATION); - seterrobj(CONTROL_NOT_FOUND); - seterrobj(DECODING_ERROR); - seterrobj(ENCODING_ERROR); - seterrobj(FILTER_ERROR); - seterrobj(INAPPROPRIATE_AUTH); - seterrobj(INAPPROPRIATE_MATCHING); - seterrobj(INSUFFICIENT_ACCESS); - seterrobj(INVALID_CREDENTIALS); - seterrobj(INVALID_DN_SYNTAX); - seterrobj(INVALID_SYNTAX); - seterrobj(IS_LEAF); - seterrobj(LOCAL_ERROR); - seterrobj(LOOP_DETECT); - seterrobj(MORE_RESULTS_TO_RETURN); - seterrobj(NAMING_VIOLATION); - seterrobj(NO_MEMORY); - seterrobj(NO_OBJECT_CLASS_MODS); - seterrobj(NO_OBJECT_CLASS_MODS); - seterrobj(NO_RESULTS_RETURNED); - seterrobj(NO_SUCH_ATTRIBUTE); - seterrobj(NO_SUCH_OBJECT); - seterrobj(NOT_ALLOWED_ON_NONLEAF); - seterrobj(NOT_ALLOWED_ON_RDN); - seterrobj(NOT_SUPPORTED); - seterrobj(OBJECT_CLASS_VIOLATION); - seterrobj(OPERATIONS_ERROR); - seterrobj(OTHER); - seterrobj(PARAM_ERROR); - seterrobj(PARTIAL_RESULTS); - seterrobj(PROTOCOL_ERROR); - seterrobj(REFERRAL); - seterrobj(REFERRAL_LIMIT_EXCEEDED); - seterrobj(RESULTS_TOO_LARGE); - seterrobj(SASL_BIND_IN_PROGRESS); - seterrobj(SERVER_DOWN); - seterrobj(SIZELIMIT_EXCEEDED); - seterrobj(STRONG_AUTH_NOT_SUPPORTED); - seterrobj(STRONG_AUTH_REQUIRED); - seterrobj(SUCCESS); - seterrobj(TIMELIMIT_EXCEEDED); - seterrobj(TIMEOUT); - seterrobj(TYPE_OR_VALUE_EXISTS); - seterrobj(UNAVAILABLE); - seterrobj(UNAVAILABLE_CRITICAL_EXTENSION); - seterrobj(UNDEFINED_TYPE); - seterrobj(UNWILLING_TO_PERFORM); - seterrobj(USER_CANCELLED); - seterrobj(VLV_ERROR); - seterrobj(X_PROXY_AUTHZ_FAILURE); - -#ifdef LDAP_API_FEATURE_CANCEL - seterrobj(CANCELLED); - seterrobj(NO_SUCH_OPERATION); - seterrobj(TOO_LATE); - seterrobj(CANNOT_CANCEL); -#endif - -#ifdef LDAP_ASSERTION_FAILED - seterrobj(ASSERTION_FAILED); -#endif - -#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED - seterrobj(PROXIED_AUTHORIZATION_DENIED); -#endif - -} diff --git a/Modules/errors.h b/Modules/errors.h deleted file mode 100644 index 5bd3576..0000000 --- a/Modules/errors.h +++ /dev/null @@ -1,16 +0,0 @@ -/* See https://www.python-ldap.org/ for details. */ - -#ifndef __h_errors_ -#define __h_errors_ - -#include "common.h" -#include "lber.h" -#include "ldap.h" - -extern PyObject* LDAPexception_class; -extern PyObject* LDAPerror( LDAP*, char*msg ); -extern PyObject* LDAPerror_TypeError(const char *, PyObject *); -extern void LDAPinit_errors( PyObject* ); -PyObject* LDAPerr(int errnum); - -#endif /* __h_errors */ diff --git a/Modules/functions.c b/Modules/functions.c index ffb6765..a31be05 100644 --- a/Modules/functions.c +++ b/Modules/functions.c @@ -4,7 +4,7 @@ #include "functions.h" #include "LDAPObject.h" #include "berval.h" -#include "errors.h" +#include "constants.h" #include "options.h" /* ldap_initialize */ diff --git a/Modules/ldapcontrol.c b/Modules/ldapcontrol.c index 7e31f72..3f5b2c4 100644 --- a/Modules/ldapcontrol.c +++ b/Modules/ldapcontrol.c @@ -4,7 +4,6 @@ #include "LDAPObject.h" #include "ldapcontrol.h" #include "berval.h" -#include "errors.h" #include "lber.h" diff --git a/Modules/ldapmodule.c b/Modules/ldapmodule.c index 46c9c8a..ec3a264 100644 --- a/Modules/ldapmodule.c +++ b/Modules/ldapmodule.c @@ -2,7 +2,6 @@ #include "common.h" #include "constants.h" -#include "errors.h" #include "functions.h" #include "ldapcontrol.h" @@ -67,8 +66,10 @@ PyObject* init_ldap_module() init_pkginfo(m); - LDAPinit_constants(d); - LDAPinit_errors(d); + if (LDAPinit_constants(m) == -1) { + return NULL; + } + LDAPinit_functions(d); LDAPinit_control(d); diff --git a/Modules/message.c b/Modules/message.c index 1a289db..babbd25 100644 --- a/Modules/message.c +++ b/Modules/message.c @@ -3,7 +3,6 @@ #include "common.h" #include "message.h" #include "berval.h" -#include "errors.h" #include "ldapcontrol.h" #include "constants.h" diff --git a/Modules/options.c b/Modules/options.c index 7cf996b..ac1eab6 100644 --- a/Modules/options.c +++ b/Modules/options.c @@ -1,7 +1,7 @@ /* See https://www.python-ldap.org/ for details. */ #include "common.h" -#include "errors.h" +#include "constants.h" #include "LDAPObject.h" #include "ldapcontrol.h" #include "options.h" diff --git a/setup.py b/setup.py index 2ac63ec..9694fa5 100644 --- a/setup.py +++ b/setup.py @@ -136,7 +136,6 @@ class OpenLDAP2: 'Modules/ldapcontrol.c', 'Modules/common.c', 'Modules/constants.c', - 'Modules/errors.c', 'Modules/functions.c', 'Modules/ldapmodule.c', 'Modules/message.c',