LCOV - code coverage report
Current view: top level - Modules - options.c (source / functions) Hit Total Coverage
Test: python-ldap LCOV report Lines: 121 131 92.4 %
Date: 2017-12-08 13:03:20 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* See https://www.python-ldap.org/ for details. */
       2             : 
       3             : #include "common.h"
       4             : #include "constants.h"
       5             : #include "LDAPObject.h"
       6             : #include "ldapcontrol.h"
       7             : #include "options.h"
       8             : 
       9             : void
      10          66 : set_timeval_from_double( struct timeval *tv, double d ) {
      11          66 :         tv->tv_usec = (long) ( fmod(d, 1.0) * 1000000.0 );
      12          66 :         tv->tv_sec = (long) floor(d);
      13          66 : }
      14             : 
      15             : /**
      16             :  * Converts a return code from ldap_set_option() or ldap_get_option()
      17             :  * into a python error, and returns NULL.
      18             :  */
      19             : static PyObject *
      20           1 : option_error(int res, const char *fn)
      21             : {
      22           1 :     if (res == LDAP_OPT_ERROR)
      23           1 :         PyErr_SetString(PyExc_ValueError, "option error");
      24           0 :     else if (res == LDAP_PARAM_ERROR)
      25           0 :         PyErr_SetString(PyExc_ValueError, "parameter error");
      26           0 :     else if (res == LDAP_NO_MEMORY) 
      27           0 :         PyErr_NoMemory();
      28             :     else
      29           0 :         PyErr_Format(PyExc_SystemError, "error %d from %s", res, fn);
      30           1 :     return NULL;
      31             : }
      32             : 
      33             : /**
      34             :  * Sets an LDAP option.
      35             :  * Returns 0 on failure, 1 on success
      36             :  */
      37             : int
      38         239 : LDAP_set_option(LDAPObject *self, int option, PyObject *value)
      39             : {
      40             :     int res;
      41             :     int intval;
      42             :     double doubleval;
      43             :     char *strval;
      44             :     struct timeval tv;
      45             :     void *ptr;
      46             :     LDAP *ld;
      47         239 :     LDAPControl **controls = NULL;
      48             : 
      49         239 :     ld = self ? self->ldap : NULL;
      50             : 
      51         239 :     switch(option) {
      52           2 :     case LDAP_OPT_API_INFO:
      53             :     case LDAP_OPT_API_FEATURE_INFO:
      54             : #ifdef HAVE_SASL
      55             :     case LDAP_OPT_X_SASL_SSF:
      56             : #endif
      57             :             /* Read-only options */
      58           2 :             PyErr_SetString(PyExc_ValueError, "read-only option");
      59         241 :             return 0;
      60           5 :     case LDAP_OPT_REFERRALS:
      61             :     case LDAP_OPT_RESTART:
      62             : #ifdef LDAP_OPT_X_SASL_NOCANON
      63             :     case LDAP_OPT_X_SASL_NOCANON:
      64             : #endif
      65             : #ifdef LDAP_OPT_CONNECT_ASYNC
      66             :     case LDAP_OPT_CONNECT_ASYNC:
      67             : #endif
      68             :             /* Truth-value options */
      69           5 :             ptr = PyObject_IsTrue(value) ? LDAP_OPT_ON : LDAP_OPT_OFF;
      70           5 :             break;
      71             : 
      72         165 :     case LDAP_OPT_DEREF:
      73             :     case LDAP_OPT_SIZELIMIT:
      74             :     case LDAP_OPT_TIMELIMIT:
      75             :     case LDAP_OPT_PROTOCOL_VERSION:
      76             :     case LDAP_OPT_ERROR_NUMBER:
      77             :     case LDAP_OPT_DEBUG_LEVEL:
      78             : #ifdef HAVE_TLS
      79             :     case LDAP_OPT_X_TLS:
      80             :     case LDAP_OPT_X_TLS_REQUIRE_CERT:
      81             : #ifdef LDAP_OPT_X_TLS_CRLCHECK
      82             :     case LDAP_OPT_X_TLS_CRLCHECK:
      83             : #endif
      84             : #ifdef LDAP_OPT_X_TLS_NEWCTX
      85             :     case LDAP_OPT_X_TLS_NEWCTX:
      86             : #endif
      87             : #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
      88             :     case LDAP_OPT_X_TLS_PROTOCOL_MIN:
      89             : #endif
      90             : #endif
      91             : #ifdef HAVE_SASL
      92             :     case LDAP_OPT_X_SASL_SSF_MIN:
      93             :     case LDAP_OPT_X_SASL_SSF_MAX:
      94             : #endif
      95             : #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
      96             :     case LDAP_OPT_X_KEEPALIVE_IDLE:
      97             : #endif
      98             : #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
      99             :     case LDAP_OPT_X_KEEPALIVE_PROBES:
     100             : #endif
     101             : #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
     102             :     case LDAP_OPT_X_KEEPALIVE_INTERVAL:
     103             : #endif
     104             : 
     105             :             /* integer value options */
     106         165 :             if (!PyArg_Parse(value, "i:set_option", &intval))
     107           1 :                 return 0;
     108         164 :             ptr = &intval;
     109         164 :             break;
     110          13 :     case LDAP_OPT_HOST_NAME:
     111             :     case LDAP_OPT_URI:
     112             : #ifdef LDAP_OPT_DEFBASE
     113             :     case LDAP_OPT_DEFBASE:
     114             : #endif
     115             :     case LDAP_OPT_ERROR_STRING:
     116             :     case LDAP_OPT_MATCHED_DN:
     117             : #ifdef HAVE_TLS
     118             :     case LDAP_OPT_X_TLS_CACERTFILE:
     119             :     case LDAP_OPT_X_TLS_CACERTDIR:
     120             :     case LDAP_OPT_X_TLS_CERTFILE:
     121             :     case LDAP_OPT_X_TLS_KEYFILE:
     122             :     case LDAP_OPT_X_TLS_CIPHER_SUITE:
     123             :     case LDAP_OPT_X_TLS_RANDOM_FILE:
     124             :     case LDAP_OPT_X_TLS_DHFILE:
     125             : #ifdef LDAP_OPT_X_TLS_CRLFILE
     126             :     case LDAP_OPT_X_TLS_CRLFILE:
     127             : #endif
     128             : #endif
     129             : #ifdef HAVE_SASL
     130             :     case LDAP_OPT_X_SASL_SECPROPS:
     131             : #endif
     132             :             /* String valued options */
     133          13 :             if (!PyArg_Parse(value, "s:set_option", &strval))
     134           2 :                 return 0;
     135          11 :             ptr = strval;
     136          11 :             break;
     137          28 :     case LDAP_OPT_TIMEOUT:
     138             :     case LDAP_OPT_NETWORK_TIMEOUT:
     139             :             /* Float valued timeval options */
     140          28 :             if (!PyArg_Parse(value, "d:set_option", &doubleval))
     141           4 :                 return 0;
     142          24 :             if (doubleval >= 0) {
     143           8 :                 set_timeval_from_double( &tv, doubleval );
     144           8 :                 ptr = &tv;
     145          16 :             } else if (doubleval == -1) {
     146             :                 /* -1 is infinity timeout */
     147          12 :                 tv.tv_sec = -1;
     148          12 :                 tv.tv_usec = 0;
     149          12 :                 ptr = &tv;
     150             :             } else {
     151           4 :                 PyErr_Format(
     152             :                     PyExc_ValueError,
     153             :                     "timeout must be >= 0 or -1 for infinity, got %d",
     154             :                     option
     155             :                 );
     156           4 :                 return 0;
     157             :             }
     158          20 :             break;
     159          24 :     case LDAP_OPT_SERVER_CONTROLS:
     160             :     case LDAP_OPT_CLIENT_CONTROLS:
     161          24 :             if (!LDAPControls_from_object(value, &controls))
     162           6 :                 return 0;
     163          18 :             ptr = controls;
     164          18 :             break;
     165           2 :     default:
     166           2 :             PyErr_Format(PyExc_ValueError, "unknown option %d", option);
     167           2 :             return 0;
     168             :     }
     169             :         
     170         218 :     if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     171         218 :     res = ldap_set_option(ld, option, ptr);
     172         218 :     if (self) LDAP_END_ALLOW_THREADS(self);
     173             : 
     174         218 :     if ((option == LDAP_OPT_SERVER_CONTROLS) || (option == LDAP_OPT_CLIENT_CONTROLS))
     175          18 :         LDAPControl_List_DEL(controls);
     176             :     
     177         218 :     if (res != LDAP_OPT_SUCCESS) {
     178           0 :         option_error(res, "ldap_set_option");
     179           0 :         return 0;
     180             :     }
     181             : 
     182         218 :     return 1;
     183             : }
     184             : 
     185             : PyObject *
     186          80 : LDAP_get_option(LDAPObject *self, int option)
     187             : {
     188             :     int res;
     189             :     int intval;
     190             :     struct timeval *tv;
     191             :     LDAPAPIInfo apiinfo;
     192             :     LDAPControl **lcs;
     193             :     char *strval;
     194             :     PyObject *extensions, *v;
     195             :     Py_ssize_t i, num_extensions;
     196             :     LDAP *ld;
     197             : 
     198          80 :     ld = self ? self->ldap : NULL;
     199             : 
     200          80 :     switch(option) {
     201           3 :     case LDAP_OPT_API_INFO:
     202           3 :             apiinfo.ldapai_info_version = LDAP_API_INFO_VERSION;
     203           3 :             if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     204           3 :             res = ldap_get_option( ld, option, &apiinfo );
     205           3 :             if (self) LDAP_END_ALLOW_THREADS(self);
     206           3 :             if (res != LDAP_OPT_SUCCESS)
     207          80 :                 return option_error(res, "ldap_get_option");
     208             :     
     209             :             /* put the extensions into tuple form */
     210           3 :             num_extensions = 0;
     211          21 :             while (apiinfo.ldapai_extensions[num_extensions])
     212          15 :                 num_extensions++;
     213           3 :             extensions = PyTuple_New(num_extensions);
     214          18 :             for (i = 0; i < num_extensions; i++)
     215          15 :                 PyTuple_SET_ITEM(extensions, i,
     216             :                     PyUnicode_FromString(apiinfo.ldapai_extensions[i]));
     217             : 
     218             :             /* return api info as a dictionary */
     219           3 :             v = Py_BuildValue("{s:i, s:i, s:i, s:s, s:i, s:O}",
     220             :                     "info_version",     apiinfo.ldapai_info_version,
     221             :                     "api_version",      apiinfo.ldapai_api_version,
     222             :                     "protocol_version", apiinfo.ldapai_protocol_version,
     223             :                     "vendor_name",      apiinfo.ldapai_vendor_name,
     224             :                     "vendor_version",   apiinfo.ldapai_vendor_version,
     225             :                     "extensions",       extensions);
     226             : 
     227           3 :             if (apiinfo.ldapai_vendor_name)
     228           3 :                 ldap_memfree(apiinfo.ldapai_vendor_name);
     229          18 :             for (i = 0; i < num_extensions; i++)
     230          15 :                 ldap_memfree(apiinfo.ldapai_extensions[i]);
     231           3 :             ldap_memfree(apiinfo.ldapai_extensions);
     232           3 :             Py_DECREF(extensions);
     233             : 
     234           3 :             return v;
     235             : 
     236             : #ifdef HAVE_SASL
     237           5 :     case LDAP_OPT_X_SASL_SSF:
     238             : #endif
     239             :     case LDAP_OPT_REFERRALS:
     240             :     case LDAP_OPT_RESTART:
     241             :     case LDAP_OPT_DEREF:
     242             :     case LDAP_OPT_SIZELIMIT:
     243             :     case LDAP_OPT_TIMELIMIT:
     244             :     case LDAP_OPT_PROTOCOL_VERSION:
     245             :     case LDAP_OPT_ERROR_NUMBER:
     246             :     case LDAP_OPT_DEBUG_LEVEL:
     247             :     case LDAP_OPT_DESC:
     248             : #ifdef HAVE_TLS
     249             :     case LDAP_OPT_X_TLS:
     250             :     case LDAP_OPT_X_TLS_REQUIRE_CERT:
     251             : #ifdef LDAP_OPT_X_TLS_CRLCHECK
     252             :     case LDAP_OPT_X_TLS_CRLCHECK:
     253             : #endif
     254             : #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
     255             :     case LDAP_OPT_X_TLS_PROTOCOL_MIN:
     256             : #endif
     257             : #endif
     258             : #ifdef HAVE_SASL
     259             :     case LDAP_OPT_X_SASL_SSF_MIN:
     260             :     case LDAP_OPT_X_SASL_SSF_MAX:
     261             : #endif
     262             : #ifdef LDAP_OPT_X_SASL_NOCANON
     263             :     case LDAP_OPT_X_SASL_NOCANON:
     264             : #endif
     265             : #ifdef LDAP_OPT_CONNECT_ASYNC
     266             :     case LDAP_OPT_CONNECT_ASYNC:
     267             : #endif
     268             : #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
     269             :     case LDAP_OPT_X_KEEPALIVE_IDLE:
     270             : #endif
     271             : #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
     272             :     case LDAP_OPT_X_KEEPALIVE_PROBES:
     273             : #endif
     274             : #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
     275             :     case LDAP_OPT_X_KEEPALIVE_INTERVAL:
     276             : #endif
     277             :             /* Integer-valued options */
     278           5 :             if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     279           5 :             res = ldap_get_option(ld, option, &intval);
     280           5 :             if (self) LDAP_END_ALLOW_THREADS(self);
     281           5 :             if (res != LDAP_OPT_SUCCESS)
     282           0 :                 return option_error(res, "ldap_get_option");
     283           5 :             return PyInt_FromLong(intval);
     284             : 
     285          10 :     case LDAP_OPT_HOST_NAME:
     286             :     case LDAP_OPT_URI:
     287             : #ifdef LDAP_OPT_DEFBASE
     288             :     case LDAP_OPT_DEFBASE:
     289             : #endif
     290             :     case LDAP_OPT_ERROR_STRING:
     291             :     case LDAP_OPT_MATCHED_DN:
     292             : #ifdef HAVE_TLS
     293             :     case LDAP_OPT_X_TLS_CACERTFILE:
     294             :     case LDAP_OPT_X_TLS_CACERTDIR:
     295             :     case LDAP_OPT_X_TLS_CERTFILE:
     296             :     case LDAP_OPT_X_TLS_KEYFILE:
     297             :     case LDAP_OPT_X_TLS_CIPHER_SUITE:
     298             :     case LDAP_OPT_X_TLS_RANDOM_FILE:
     299             :     case LDAP_OPT_X_TLS_DHFILE:
     300             : #ifdef LDAP_OPT_X_TLS_CRLFILE
     301             :     case LDAP_OPT_X_TLS_CRLFILE:
     302             : #endif
     303             : #ifdef LDAP_OPT_X_TLS_VERSION
     304             :     case LDAP_OPT_X_TLS_VERSION:
     305             : #endif
     306             : #ifdef LDAP_OPT_X_TLS_CIPHER
     307             :     case LDAP_OPT_X_TLS_CIPHER:
     308             : #endif
     309             : #ifdef LDAP_OPT_X_TLS_PACKAGE
     310             :     case LDAP_OPT_X_TLS_PACKAGE:
     311             : #endif
     312             : #endif
     313             : #ifdef HAVE_SASL
     314             :     case LDAP_OPT_X_SASL_SECPROPS:
     315             :     case LDAP_OPT_X_SASL_MECH:
     316             :     case LDAP_OPT_X_SASL_REALM:
     317             :     case LDAP_OPT_X_SASL_AUTHCID:
     318             :     case LDAP_OPT_X_SASL_AUTHZID:
     319             : #ifdef LDAP_OPT_X_SASL_USERNAME
     320             :     case LDAP_OPT_X_SASL_USERNAME:
     321             : #endif
     322             : #endif
     323             :             /* String-valued options */
     324          10 :             if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     325          10 :             res = ldap_get_option(ld, option, &strval);
     326          10 :             if (self) LDAP_END_ALLOW_THREADS(self);
     327          10 :             if (res != LDAP_OPT_SUCCESS)
     328           1 :                 return option_error(res, "ldap_get_option");
     329           9 :             if (strval == NULL) {
     330           2 :                 Py_INCREF(Py_None);
     331           2 :                 return Py_None;
     332             :             }
     333           7 :             v = PyUnicode_FromString(strval);
     334           7 :             ldap_memfree(strval);
     335           7 :             return v;
     336             : 
     337          32 :     case LDAP_OPT_TIMEOUT:
     338             :     case LDAP_OPT_NETWORK_TIMEOUT:
     339             :             /* Double-valued timeval options */
     340          32 :             if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     341          32 :             res = ldap_get_option(ld, option, &tv);
     342          32 :             if (self) LDAP_END_ALLOW_THREADS(self);
     343          32 :             if (res != LDAP_OPT_SUCCESS)
     344           0 :                 return option_error(res, "ldap_get_option");
     345          32 :             if (tv == NULL) {
     346          24 :                 Py_INCREF(Py_None);
     347          24 :                 return Py_None;
     348             :             }
     349           8 :             v = PyFloat_FromDouble(
     350           8 :               (double) tv->tv_sec + ( (double) tv->tv_usec / 1000000.0 )
     351             :             );
     352           8 :             ldap_memfree(tv);
     353           8 :             return v;
     354             : 
     355          28 :     case LDAP_OPT_SERVER_CONTROLS:
     356             :     case LDAP_OPT_CLIENT_CONTROLS:
     357          28 :             if (self) LDAP_BEGIN_ALLOW_THREADS(self);
     358          28 :             res = ldap_get_option(ld, option, &lcs);
     359          28 :             if (self) LDAP_END_ALLOW_THREADS(self);
     360             : 
     361          28 :             if (res != LDAP_OPT_SUCCESS)
     362           0 :                 return option_error(res, "ldap_get_option");
     363             : 
     364          28 :             v = LDAPControls_to_List(lcs);
     365          28 :             ldap_controls_free(lcs);
     366          28 :             return v;
     367             :             
     368           2 :     default:
     369           2 :             PyErr_Format(PyExc_ValueError, "unknown option %d", option);
     370           2 :             return NULL;
     371             :     }
     372             : }

Generated by: LCOV version 1.12