From 30fb0a8bda8fbedc22de87b21b8b1b64de310a6b Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 28 Jun 2021 11:03:02 +0200 Subject: [PATCH] Fix SASL get/set options on big endian platforms The options OPT_X_SASL_SSF_MIN, OPT_X_SASL_SSF_MAX, and OPT_X_SASL_SSF take *ber_len_t as input and output arguments. ber_len_t is defined as unsigned long: ``` /* LBER lengths (32 bits or larger) */ #define LBER_LEN_T long typedef unsigned LBER_LEN_T ber_len_t; ``` Wrong type handling is causing issues on big endian platforms. Signed-off-by: Christian Heimes --- Modules/options.c | 41 ++++++++++++++++++++++++++++++----------- Tests/t_ldapobject.py | 23 ++++++++++++++++++++++- 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/Modules/options.c b/Modules/options.c index 549a672..67511e8 100644 --- a/Modules/options.c +++ b/Modules/options.c @@ -43,6 +43,10 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value) double doubleval; char *strval; struct timeval tv; +#if HAVE_SASL + /* unsigned long */ + ber_len_t blen; +#endif void *ptr; LDAP *ld; LDAPControl **controls = NULL; @@ -89,10 +93,6 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value) case LDAP_OPT_X_TLS_PROTOCOL_MIN: #endif #endif -#ifdef HAVE_SASL - case LDAP_OPT_X_SASL_SSF_MIN: - case LDAP_OPT_X_SASL_SSF_MAX: -#endif #ifdef LDAP_OPT_X_KEEPALIVE_IDLE case LDAP_OPT_X_KEEPALIVE_IDLE: #endif @@ -108,6 +108,16 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value) return 0; ptr = &intval; break; + +#ifdef HAVE_SASL + case LDAP_OPT_X_SASL_SSF_MIN: + case LDAP_OPT_X_SASL_SSF_MAX: + if (!PyArg_Parse(value, "k:set_option", &blen)) + return 0; + ptr = &blen; + break; +#endif + case LDAP_OPT_HOST_NAME: case LDAP_OPT_URI: #ifdef LDAP_OPT_DEFBASE @@ -135,6 +145,7 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value) return 0; ptr = strval; break; + case LDAP_OPT_TIMEOUT: case LDAP_OPT_NETWORK_TIMEOUT: /* Float valued timeval options */ @@ -239,6 +250,10 @@ LDAP_get_option(LDAPObject *self, int option) LDAPAPIInfo apiinfo; LDAPControl **lcs; char *strval; +#if HAVE_SASL + /* unsigned long */ + ber_len_t blen; +#endif PyObject *extensions, *v; Py_ssize_t i, num_extensions; @@ -277,9 +292,6 @@ LDAP_get_option(LDAPObject *self, int option) return v; -#ifdef HAVE_SASL - case LDAP_OPT_X_SASL_SSF: -#endif case LDAP_OPT_REFERRALS: case LDAP_OPT_RESTART: case LDAP_OPT_DEREF: @@ -299,10 +311,6 @@ LDAP_get_option(LDAPObject *self, int option) case LDAP_OPT_X_TLS_PROTOCOL_MIN: #endif #endif -#ifdef HAVE_SASL - case LDAP_OPT_X_SASL_SSF_MIN: - case LDAP_OPT_X_SASL_SSF_MAX: -#endif #ifdef LDAP_OPT_X_SASL_NOCANON case LDAP_OPT_X_SASL_NOCANON: #endif @@ -324,6 +332,17 @@ LDAP_get_option(LDAPObject *self, int option) return option_error(res, "ldap_get_option"); return PyInt_FromLong(intval); +#ifdef HAVE_SASL + case LDAP_OPT_X_SASL_SSF: + case LDAP_OPT_X_SASL_SSF_MIN: + case LDAP_OPT_X_SASL_SSF_MAX: +#endif + /* ber_len_t options (unsigned long)*/ + res = LDAP_int_get_option(self, option, &blen); + if (res != LDAP_OPT_SUCCESS) + return option_error(res, "ldap_get_option"); + return PyLong_FromUnsignedLong(blen); + case LDAP_OPT_HOST_NAME: case LDAP_OPT_URI: #ifdef LDAP_OPT_DEFBASE diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index e54bbfd..0a089c9 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -334,7 +334,7 @@ class Test00_SimpleLDAPObject(SlapdTestCase): @requires_sasl() @requires_ldapi() - def test006_sasl_extenal_bind_s(self): + def test006_sasl_external_bind_s(self): l = self.ldap_object_class(self.server.ldapi_uri) l.sasl_external_bind_s() self.assertEqual(l.whoami_s(), 'dn:'+self.server.root_dn.lower()) @@ -343,6 +343,27 @@ class Test00_SimpleLDAPObject(SlapdTestCase): l.sasl_external_bind_s(authz_id=authz_id) self.assertEqual(l.whoami_s(), authz_id.lower()) + @requires_sasl() + @requires_ldapi() + def test006_sasl_options(self): + l = self.ldap_object_class(self.server.ldapi_uri) + + minssf = l.get_option(ldap.OPT_X_SASL_SSF_MIN) + self.assertGreaterEqual(minssf, 0) + self.assertLessEqual(minssf, 256) + maxssf = l.get_option(ldap.OPT_X_SASL_SSF_MAX) + self.assertGreaterEqual(maxssf, 0) + # libldap sets SSF_MAX to INT_MAX + self.assertLessEqual(maxssf, 2**31 - 1) + + l.set_option(ldap.OPT_X_SASL_SSF_MIN, 56) + l.set_option(ldap.OPT_X_SASL_SSF_MAX, 256) + self.assertEqual(l.get_option(ldap.OPT_X_SASL_SSF_MIN), 56) + self.assertEqual(l.get_option(ldap.OPT_X_SASL_SSF_MAX), 256) + + l.sasl_external_bind_s() + self.assertEqual(l.whoami_s(), 'dn:' + self.server.root_dn.lower()) + def test007_timeout(self): l = self.ldap_object_class(self.server.ldap_uri) m = l.search_ext(self.server.suffix, ldap.SCOPE_SUBTREE, '(objectClass=*)') -- 2.31.1