LCOV - code coverage report
Current view: top level - Modules - ldapcontrol.c (source / functions) Hit Total Coverage
Test: python-ldap LCOV report Lines: 139 186 74.7 %
Date: 2017-12-08 13:03:20 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* See https://www.python-ldap.org/ for details. */
       2             : 
       3             : #include "common.h"
       4             : #include "LDAPObject.h"
       5             : #include "ldapcontrol.h"
       6             : #include "berval.h"
       7             : #include "constants.h"
       8             : 
       9             : #include "lber.h"
      10             : 
      11             : /* Prints to stdout the contents of an array of LDAPControl objects */
      12             : 
      13             : /* XXX: This is a debugging tool, and the printf generates some warnings
      14             :  * about pointer types. I left it here in case something breaks and we
      15             :  * need to inspect an LDAPControl structure.
      16             : 
      17             : static void
      18             : LDAPControl_DumpList( LDAPControl** lcs ) {
      19             :     LDAPControl** lcp;
      20             :     LDAPControl* lc;
      21             :         for ( lcp = lcs; *lcp; lcp++ ) {
      22             :         lc = *lcp;
      23             :         printf("OID: %s\nCriticality: %d\nBER length: %d\nBER value: %x\n",
      24             :             lc->ldctl_oid, lc->ldctl_iscritical, lc->ldctl_value.bv_len,
      25             :             lc->ldctl_value.bv_val);
      26             :     }
      27             : } */
      28             : 
      29             : /* Free a single LDAPControl object created by Tuple_to_LDAPControl */
      30             :   
      31             : static void
      32          14 : LDAPControl_DEL( LDAPControl* lc )
      33             : {
      34          14 :     if (lc == NULL)
      35           0 :         return;
      36             :   
      37          14 :     if (lc->ldctl_oid)
      38          14 :         PyMem_DEL(lc->ldctl_oid);
      39          14 :     PyMem_DEL(lc);
      40             : }
      41             : 
      42             : /* Free an array of LDAPControl objects created by LDAPControls_from_object */
      43             : 
      44             : void
      45         453 : LDAPControl_List_DEL( LDAPControl** lcs )
      46             : {
      47             :     LDAPControl** lcp;
      48         453 :     if (lcs == NULL)
      49         429 :         return;
      50             : 
      51          38 :     for ( lcp = lcs; *lcp; lcp++ )
      52          14 :         LDAPControl_DEL( *lcp );
      53             : 
      54          24 :     PyMem_DEL( lcs );
      55             : }
      56             : 
      57             : /* Takes a tuple of the form:
      58             :  * (OID: string, Criticality: int/boolean, Value: string/None)
      59             :  * and converts it into an LDAPControl structure.
      60             :  *
      61             :  * The Value string should represent an ASN.1 encoded structure.
      62             :  */
      63             : 
      64             : static LDAPControl*
      65          18 : Tuple_to_LDAPControl( PyObject* tup )
      66             : {
      67             :     char *oid;
      68             :     char iscritical;
      69             :     struct berval berbytes;
      70             :     PyObject *bytes;
      71          18 :     LDAPControl *lc = NULL;
      72             :     Py_ssize_t len;
      73             : 
      74          18 :     if (!PyTuple_Check(tup)) {
      75           4 :       LDAPerror_TypeError("expected a tuple", tup);
      76          22 :       return NULL;
      77             :     }
      78             : 
      79          14 :     if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
      80           0 :         return NULL;
      81             :   
      82          14 :     lc = PyMem_NEW(LDAPControl, 1);
      83          14 :     if (lc == NULL) {
      84           0 :         PyErr_NoMemory();
      85           0 :         return NULL;
      86             :     }
      87             : 
      88          14 :     lc->ldctl_iscritical = iscritical;
      89             : 
      90          14 :     len = strlen(oid);
      91          14 :     lc->ldctl_oid = PyMem_NEW(char, len + 1);
      92          14 :     if (lc->ldctl_oid == NULL) {
      93           0 :         PyErr_NoMemory();
      94           0 :         LDAPControl_DEL(lc);
      95           0 :         return NULL;
      96             :     }
      97          14 :     memcpy(lc->ldctl_oid, oid, len + 1);
      98             : 
      99             :     /* The berval can either be None or a String */
     100          14 :     if (PyNone_Check(bytes)) {
     101           4 :         berbytes.bv_len = 0;
     102           4 :         berbytes.bv_val = NULL;
     103             :     }
     104          10 :     else if (PyBytes_Check(bytes)) {
     105          10 :         berbytes.bv_len = PyBytes_Size(bytes);
     106          10 :         berbytes.bv_val = PyBytes_AsString(bytes);
     107             :     }
     108             :     else {
     109           0 :         LDAPerror_TypeError("expected bytes", bytes);
     110           0 :         LDAPControl_DEL(lc);
     111           0 :         return NULL;
     112             :     }
     113             :     
     114          14 :     lc->ldctl_value = berbytes;
     115             : 
     116          14 :     return lc;
     117             : }
     118             : 
     119             : /* Convert a list of tuples (of a format acceptable to the Tuple_to_LDAPControl
     120             :  * function) into an array of LDAPControl objects. */
     121             : 
     122             : int
     123          60 : LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
     124             : {
     125             :     Py_ssize_t len, i;
     126             :     LDAPControl** ldcs;
     127             :     LDAPControl* ldc;
     128             :     PyObject* item;
     129             :   
     130          60 :     if (!PySequence_Check(list)) {
     131          32 :         LDAPerror_TypeError("expected a list", list);
     132          32 :         return 0;
     133             :     }
     134             : 
     135          28 :     len = PySequence_Length(list);
     136          28 :     ldcs = PyMem_NEW(LDAPControl*, len + 1);
     137          28 :     if (ldcs == NULL) {
     138           0 :         PyErr_NoMemory();
     139           0 :         return 0;
     140             :     }
     141             : 
     142          42 :     for (i = 0; i < len; i++) {
     143          18 :       item = PySequence_GetItem(list, i);
     144          18 :       if (item == NULL) {
     145           0 :           PyMem_DEL(ldcs);
     146           0 :           return 0;
     147             :       }
     148             : 
     149          18 :       ldc = Tuple_to_LDAPControl(item);
     150          18 :       if (ldc == NULL) {
     151           4 :           Py_DECREF(item);
     152           4 :           PyMem_DEL(ldcs);
     153           4 :           return 0;
     154             :       }
     155             : 
     156          14 :       ldcs[i] = ldc;
     157          14 :       Py_DECREF(item);
     158             :     }
     159             : 
     160          24 :     ldcs[len] = NULL;
     161          24 :     *controls_ret = ldcs;
     162          24 :     return 1;
     163             : }
     164             : 
     165             : PyObject*
     166         267 : LDAPControls_to_List(LDAPControl **ldcs)
     167             : {
     168         267 :     PyObject *res = 0, *pyctrl;
     169         267 :     LDAPControl **tmp = ldcs;
     170         267 :     Py_ssize_t num_ctrls = 0, i;
     171             : 
     172         267 :     if (tmp)
     173          33 :         while (*tmp++) num_ctrls++;
     174             : 
     175         267 :     if ((res = PyList_New(num_ctrls)) == NULL) {
     176           0 :         return NULL;
     177             :     }
     178             : 
     179         304 :     for (i = 0; i < num_ctrls; i++) {
     180         111 :         pyctrl = Py_BuildValue("sbO&",
     181          37 :                                ldcs[i]->ldctl_oid,
     182          37 :                                ldcs[i]->ldctl_iscritical,
     183          37 :                                LDAPberval_to_object, &ldcs[i]->ldctl_value);
     184          37 :         if (pyctrl == NULL) {
     185           0 :             Py_DECREF(res);
     186           0 :             return NULL;
     187             :         }
     188          37 :         PyList_SET_ITEM(res, i, pyctrl);
     189             :     }
     190         267 :     return res;
     191             : }
     192             : 
     193             : 
     194             : 
     195             : /* --------------- en-/decoders ------------- */
     196             : 
     197             : /* Matched Values, aka, Values Return Filter */
     198             : static PyObject*
     199           1 : encode_rfc3876(PyObject *self, PyObject *args)
     200             : {
     201           1 :         PyObject *res = 0;
     202             :         int err;
     203           1 :         BerElement *vrber = 0;
     204             :         char *vrFilter;
     205             :         struct berval *ctrl_val;
     206             : 
     207           1 :         if (!PyArg_ParseTuple(args, "s:encode_valuesreturnfilter_control", &vrFilter)) {
     208           0 :                 goto endlbl;
     209             :         }
     210             : 
     211           1 :         if (!(vrber = ber_alloc_t(LBER_USE_DER))) {
     212           0 :                 LDAPerr(LDAP_NO_MEMORY);
     213           0 :                 goto endlbl;
     214             :         }
     215             : 
     216           1 :         err = ldap_put_vrFilter(vrber, vrFilter);
     217           1 :         if (err == -1) {
     218           0 :                 LDAPerr(LDAP_FILTER_ERROR);
     219           0 :                 goto endlbl;
     220             :         }
     221             : 
     222           1 :         err = ber_flatten(vrber, &ctrl_val);
     223           1 :         if (err == -1) {
     224           0 :                 LDAPerr(LDAP_NO_MEMORY);
     225           0 :                 goto endlbl;
     226             :         }
     227             : 
     228           1 :         res = LDAPberval_to_object(ctrl_val);
     229           1 :         ber_bvfree(ctrl_val);
     230             : 
     231           1 : endlbl:
     232           1 :         if (vrber)
     233           1 :                 ber_free(vrber, 1);
     234             : 
     235           1 :         return res;
     236             : }
     237             : 
     238             : static PyObject*
     239           1 : encode_rfc2696(PyObject *self, PyObject *args)
     240             : {
     241           1 :     PyObject *res = 0;
     242           1 :     BerElement *ber = 0;
     243             :     struct berval cookie, *ctrl_val;
     244             :     Py_ssize_t cookie_len;
     245             :     unsigned long size;
     246             :     ber_tag_t tag;
     247             : 
     248           1 :     if (!PyArg_ParseTuple(args, "is#:encode_page_control", &size,
     249             :                           &cookie.bv_val, &cookie_len)) {
     250           0 :         goto endlbl;
     251             :     }
     252           1 :     cookie.bv_len = (ber_len_t) cookie_len;
     253             : 
     254           1 :     if (!(ber = ber_alloc_t(LBER_USE_DER))) {
     255           0 :         LDAPerr(LDAP_NO_MEMORY);
     256           0 :         goto endlbl;
     257             :     }
     258             : 
     259           1 :     tag = ber_printf(ber, "{i", size);
     260           1 :     if (tag == LBER_ERROR) {
     261           0 :         LDAPerr(LDAP_ENCODING_ERROR);
     262           0 :         goto endlbl;
     263             :     }
     264             : 
     265           1 :     if (!cookie.bv_len)
     266           0 :         tag = ber_printf(ber, "o", "", 0);
     267             :     else
     268           1 :         tag = ber_printf(ber, "O", &cookie);
     269           1 :     if (tag == LBER_ERROR) {
     270           0 :         LDAPerr(LDAP_ENCODING_ERROR);
     271           0 :         goto endlbl;
     272             :     }
     273             : 
     274           1 :     tag = ber_printf(ber, /*{ */ "N}");
     275           1 :     if (tag == LBER_ERROR) {
     276           0 :         LDAPerr(LDAP_ENCODING_ERROR);
     277           0 :         goto endlbl;
     278             :     }
     279             : 
     280           1 :     if (-1 == ber_flatten(ber, &ctrl_val)) {
     281           0 :         LDAPerr(LDAP_NO_MEMORY);
     282           0 :         goto endlbl;
     283             :     }
     284             : 
     285           1 :     res = LDAPberval_to_object(ctrl_val);
     286           1 :     ber_bvfree(ctrl_val);
     287             : 
     288           1 :  endlbl:
     289           1 :     if (ber)
     290           1 :         ber_free(ber, 1);
     291           1 :     return res;
     292             : }
     293             : 
     294             : 
     295             : static PyObject*
     296           1 : decode_rfc2696(PyObject *self, PyObject *args)
     297             : {
     298           1 :     PyObject *res = 0;
     299           1 :     BerElement *ber = 0;
     300             :     struct berval ldctl_value;
     301             :     ber_tag_t tag;
     302             :     struct berval *cookiep;
     303           1 :     unsigned long count = 0;
     304             :     Py_ssize_t ldctl_value_len;
     305             : 
     306           1 :     if (!PyArg_ParseTuple(args, "s#:decode_page_control",
     307             :                           &ldctl_value.bv_val, &ldctl_value_len)) {
     308           0 :         goto endlbl;
     309             :     }
     310           1 :     ldctl_value.bv_len = (ber_len_t) ldctl_value_len;
     311             : 
     312           1 :     if (!(ber = ber_init(&ldctl_value))) {
     313           0 :         LDAPerr(LDAP_NO_MEMORY);
     314           0 :         goto endlbl;
     315             :     }
     316             : 
     317           1 :     tag = ber_scanf(ber, "{iO", &count, &cookiep);
     318           1 :     if (tag == LBER_ERROR) {
     319           0 :         LDAPerr(LDAP_DECODING_ERROR);
     320           0 :         goto endlbl;
     321             :     }
     322             : 
     323           1 :     res = Py_BuildValue("(kO&)", count, LDAPberval_to_object, cookiep);
     324           1 :     ber_bvfree(cookiep);
     325             : 
     326           1 :  endlbl:
     327           1 :     if (ber)
     328           1 :         ber_free(ber, 1);
     329           1 :     return res;
     330             : }
     331             : 
     332             : static PyObject*
     333           1 : encode_assertion_control(PyObject *self, PyObject *args)
     334             : {
     335             :     int err;
     336           1 :     PyObject *res = 0;
     337             :     char *assertion_filterstr;
     338             :     struct berval ctrl_val;
     339           1 :     LDAP *ld = NULL;
     340             : 
     341           1 :     if (!PyArg_ParseTuple(args, "s:encode_assertion_control",
     342             :                           &assertion_filterstr)) {
     343           0 :         goto endlbl;
     344             :     }
     345             : 
     346             :     /* XXX: ldap_create() is a nasty and slow hack. It's creating a full blown
     347             :      * LDAP object just to encode assertion controls.
     348             :      */
     349           1 :     Py_BEGIN_ALLOW_THREADS
     350           1 :     err = ldap_create(&ld);
     351           1 :     Py_END_ALLOW_THREADS
     352             : 
     353           1 :     if (err != LDAP_SUCCESS)
     354           1 :         return LDAPerror(ld, "ldap_create");
     355             : 
     356           1 :     err = ldap_create_assertion_control_value(ld,assertion_filterstr,&ctrl_val);
     357             : 
     358           1 :     if (err != LDAP_SUCCESS) {
     359           0 :         LDAPerror(ld, "ldap_create_assertion_control_value");
     360           0 :         Py_BEGIN_ALLOW_THREADS
     361           0 :         ldap_unbind_ext(ld, NULL, NULL);
     362           0 :         Py_END_ALLOW_THREADS
     363           0 :         return NULL;
     364             :     }
     365           1 :     Py_BEGIN_ALLOW_THREADS
     366           1 :     ldap_unbind_ext(ld, NULL, NULL);
     367           1 :     Py_END_ALLOW_THREADS
     368             : 
     369           1 :     res = LDAPberval_to_object(&ctrl_val);
     370           1 :     if (ctrl_val.bv_val != NULL) {
     371           1 :         ber_memfree(ctrl_val.bv_val);
     372             :     }
     373           1 :     endlbl:
     374             : 
     375           1 :     return res;
     376             : }
     377             : 
     378             : static PyMethodDef methods[] = {
     379             :     {"encode_page_control", encode_rfc2696, METH_VARARGS },
     380             :     {"decode_page_control", decode_rfc2696, METH_VARARGS },
     381             :     {"encode_valuesreturnfilter_control", encode_rfc3876, METH_VARARGS },
     382             :     {"encode_assertion_control", encode_assertion_control, METH_VARARGS },
     383             :     { NULL, NULL }
     384             : };
     385             : 
     386             : void
     387           1 : LDAPinit_control(PyObject *d)
     388             : {
     389           1 :     LDAPadd_methods(d, methods);
     390           1 : }

Generated by: LCOV version 1.12