378 lines
8.4 KiB
C
378 lines
8.4 KiB
C
/* See http://www.python-ldap.org/ for details.
|
|
* $Id: ldapcontrol.c,v 1.20 2011/10/26 18:38:06 stroeder Exp $ */
|
|
|
|
#include "common.h"
|
|
#include "LDAPObject.h"
|
|
#include "ldapcontrol.h"
|
|
#include "berval.h"
|
|
#include "errors.h"
|
|
|
|
#include "lber.h"
|
|
|
|
/* Prints to stdout the contents of an array of LDAPControl objects */
|
|
|
|
/* XXX: This is a debugging tool, and the printf generates some warnings
|
|
* about pointer types. I left it here in case something breaks and we
|
|
* need to inspect an LDAPControl structure.
|
|
|
|
static void
|
|
LDAPControl_DumpList( LDAPControl** lcs ) {
|
|
LDAPControl** lcp;
|
|
LDAPControl* lc;
|
|
for ( lcp = lcs; *lcp; lcp++ ) {
|
|
lc = *lcp;
|
|
printf("OID: %s\nCriticality: %d\nBER length: %d\nBER value: %x\n",
|
|
lc->ldctl_oid, lc->ldctl_iscritical, lc->ldctl_value.bv_len,
|
|
lc->ldctl_value.bv_val);
|
|
}
|
|
} */
|
|
|
|
/* Free a single LDAPControl object created by Tuple_to_LDAPControl */
|
|
|
|
static void
|
|
LDAPControl_DEL( LDAPControl* lc )
|
|
{
|
|
if (lc == NULL)
|
|
return;
|
|
|
|
if (lc->ldctl_oid)
|
|
PyMem_DEL(lc->ldctl_oid);
|
|
PyMem_DEL(lc);
|
|
}
|
|
|
|
/* Free an array of LDAPControl objects created by LDAPControls_from_object */
|
|
|
|
void
|
|
LDAPControl_List_DEL( LDAPControl** lcs )
|
|
{
|
|
LDAPControl** lcp;
|
|
if (lcs == NULL)
|
|
return;
|
|
|
|
for ( lcp = lcs; *lcp; lcp++ )
|
|
LDAPControl_DEL( *lcp );
|
|
|
|
PyMem_DEL( lcs );
|
|
}
|
|
|
|
/* Takes a tuple of the form:
|
|
* (OID: string, Criticality: int/boolean, Value: string/None)
|
|
* and converts it into an LDAPControl structure.
|
|
*
|
|
* The Value string should represent an ASN.1 encoded structure.
|
|
*/
|
|
|
|
static LDAPControl*
|
|
Tuple_to_LDAPControl( PyObject* tup )
|
|
{
|
|
char *oid;
|
|
char iscritical;
|
|
struct berval berbytes;
|
|
PyObject *bytes;
|
|
LDAPControl *lc = NULL;
|
|
Py_ssize_t len;
|
|
|
|
if (!PyTuple_Check(tup)) {
|
|
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
|
|
"expected a tuple", tup));
|
|
return NULL;
|
|
}
|
|
|
|
if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
|
|
return NULL;
|
|
|
|
lc = PyMem_NEW(LDAPControl, 1);
|
|
if (lc == NULL) {
|
|
PyErr_NoMemory();
|
|
return NULL;
|
|
}
|
|
|
|
lc->ldctl_iscritical = iscritical;
|
|
|
|
len = strlen(oid);
|
|
lc->ldctl_oid = PyMem_NEW(char, len + 1);
|
|
if (lc->ldctl_oid == NULL) {
|
|
PyErr_NoMemory();
|
|
LDAPControl_DEL(lc);
|
|
return NULL;
|
|
}
|
|
memcpy(lc->ldctl_oid, oid, len + 1);
|
|
|
|
/* The berval can either be None or a String */
|
|
if (PyNone_Check(bytes)) {
|
|
berbytes.bv_len = 0;
|
|
berbytes.bv_val = NULL;
|
|
}
|
|
else if (PyBytes_Check(bytes)) {
|
|
berbytes.bv_len = PyBytes_Size(bytes);
|
|
berbytes.bv_val = PyBytes_AsString(bytes);
|
|
}
|
|
else {
|
|
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
|
|
"expected bytes", bytes));
|
|
LDAPControl_DEL(lc);
|
|
return NULL;
|
|
}
|
|
|
|
lc->ldctl_value = berbytes;
|
|
|
|
return lc;
|
|
}
|
|
|
|
/* Convert a list of tuples (of a format acceptable to the Tuple_to_LDAPControl
|
|
* function) into an array of LDAPControl objects. */
|
|
|
|
int
|
|
LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
|
|
{
|
|
Py_ssize_t len, i;
|
|
LDAPControl** ldcs;
|
|
LDAPControl* ldc;
|
|
PyObject* item;
|
|
|
|
if (!PySequence_Check(list)) {
|
|
PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
|
|
"expected a list", list));
|
|
return 0;
|
|
}
|
|
|
|
len = PySequence_Length(list);
|
|
ldcs = PyMem_NEW(LDAPControl*, len + 1);
|
|
if (ldcs == NULL) {
|
|
PyErr_NoMemory();
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
item = PySequence_GetItem(list, i);
|
|
if (item == NULL) {
|
|
PyMem_DEL(ldcs);
|
|
return 0;
|
|
}
|
|
|
|
ldc = Tuple_to_LDAPControl(item);
|
|
if (ldc == NULL) {
|
|
Py_DECREF(item);
|
|
PyMem_DEL(ldcs);
|
|
return 0;
|
|
}
|
|
|
|
ldcs[i] = ldc;
|
|
Py_DECREF(item);
|
|
}
|
|
|
|
ldcs[len] = NULL;
|
|
*controls_ret = ldcs;
|
|
return 1;
|
|
}
|
|
|
|
PyObject*
|
|
LDAPControls_to_List(LDAPControl **ldcs)
|
|
{
|
|
PyObject *res = 0, *pyctrl;
|
|
LDAPControl **tmp = ldcs;
|
|
Py_ssize_t num_ctrls = 0, i;
|
|
|
|
if (tmp)
|
|
while (*tmp++) num_ctrls++;
|
|
|
|
if (!(res = PyList_New(num_ctrls)))
|
|
goto endlbl;
|
|
|
|
for (i = 0; i < num_ctrls; i++) {
|
|
if (!(pyctrl = Py_BuildValue("sbO&", ldcs[i]->ldctl_oid,
|
|
ldcs[i]->ldctl_iscritical,
|
|
LDAPberval_to_object,
|
|
&ldcs[i]->ldctl_value))) {
|
|
goto endlbl;
|
|
}
|
|
PyList_SET_ITEM(res, i, pyctrl);
|
|
}
|
|
Py_INCREF(res);
|
|
|
|
endlbl:
|
|
Py_XDECREF(res);
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
/* --------------- en-/decoders ------------- */
|
|
|
|
/* Matched Values, aka, Values Return Filter */
|
|
static PyObject*
|
|
encode_rfc3876(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *res = 0;
|
|
int err;
|
|
BerElement *vrber = 0;
|
|
char *vrFilter;
|
|
struct berval *ctrl_val;
|
|
|
|
if (!PyArg_ParseTuple(args, "s:encode_valuesreturnfilter_control", &vrFilter)) {
|
|
goto endlbl;
|
|
}
|
|
|
|
if (!(vrber = ber_alloc_t(LBER_USE_DER))) {
|
|
LDAPerr(LDAP_NO_MEMORY);
|
|
goto endlbl;
|
|
}
|
|
|
|
err = ldap_put_vrFilter(vrber, vrFilter);
|
|
if (err == -1) {
|
|
LDAPerr(LDAP_FILTER_ERROR);
|
|
goto endlbl;
|
|
}
|
|
|
|
err = ber_flatten(vrber, &ctrl_val);
|
|
if (err == -1) {
|
|
LDAPerr(LDAP_NO_MEMORY);
|
|
goto endlbl;
|
|
}
|
|
|
|
res = LDAPberval_to_object(ctrl_val);
|
|
|
|
endlbl:
|
|
if (vrber)
|
|
ber_free(vrber, 1);
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyObject*
|
|
encode_rfc2696(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *res = 0;
|
|
BerElement *ber = 0;
|
|
struct berval cookie, *ctrl_val;
|
|
Py_ssize_t cookie_len;
|
|
unsigned long size;
|
|
ber_tag_t tag;
|
|
|
|
if (!PyArg_ParseTuple(args, "is#:encode_page_control", &size,
|
|
&cookie.bv_val, &cookie_len)) {
|
|
goto endlbl;
|
|
}
|
|
cookie.bv_len = (ber_len_t) cookie_len;
|
|
|
|
if (!(ber = ber_alloc_t(LBER_USE_DER))) {
|
|
LDAPerr(LDAP_NO_MEMORY);
|
|
goto endlbl;
|
|
}
|
|
|
|
tag = ber_printf(ber, "{i", size);
|
|
if (tag == LBER_ERROR) {
|
|
LDAPerr(LDAP_ENCODING_ERROR);
|
|
goto endlbl;
|
|
}
|
|
|
|
if (!cookie.bv_len)
|
|
tag = ber_printf(ber, "o", "", 0);
|
|
else
|
|
tag = ber_printf(ber, "O", &cookie);
|
|
if (tag == LBER_ERROR) {
|
|
LDAPerr(LDAP_ENCODING_ERROR);
|
|
goto endlbl;
|
|
}
|
|
|
|
tag = ber_printf(ber, /*{ */ "N}");
|
|
if (tag == LBER_ERROR) {
|
|
LDAPerr(LDAP_ENCODING_ERROR);
|
|
goto endlbl;
|
|
}
|
|
|
|
if (-1 == ber_flatten(ber, &ctrl_val)) {
|
|
LDAPerr(LDAP_NO_MEMORY);
|
|
goto endlbl;
|
|
}
|
|
|
|
res = LDAPberval_to_object(ctrl_val);
|
|
|
|
endlbl:
|
|
if (ber)
|
|
ber_free(ber, 1);
|
|
return res;
|
|
}
|
|
|
|
|
|
static PyObject*
|
|
decode_rfc2696(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *res = 0;
|
|
BerElement *ber = 0;
|
|
struct berval ldctl_value;
|
|
ber_tag_t tag;
|
|
struct berval *cookiep;
|
|
unsigned long count;
|
|
Py_ssize_t ldctl_value_len;
|
|
|
|
if (!PyArg_ParseTuple(args, "s#:decode_page_control",
|
|
&ldctl_value.bv_val, &ldctl_value_len)) {
|
|
goto endlbl;
|
|
}
|
|
ldctl_value.bv_len = (ber_len_t) ldctl_value_len;
|
|
|
|
if (!(ber = ber_init(&ldctl_value))) {
|
|
LDAPerr(LDAP_NO_MEMORY);
|
|
goto endlbl;
|
|
}
|
|
|
|
tag = ber_scanf(ber, "{iO", &count, &cookiep);
|
|
if (tag == LBER_ERROR) {
|
|
LDAPerr(LDAP_DECODING_ERROR);
|
|
goto endlbl;
|
|
}
|
|
|
|
res = Py_BuildValue("(lO&)", count, LDAPberval_to_object, cookiep);
|
|
|
|
endlbl:
|
|
if (ber)
|
|
ber_free(ber, 1);
|
|
return res;
|
|
}
|
|
|
|
static PyObject*
|
|
encode_assertion_control(PyObject *self, PyObject *args)
|
|
{
|
|
int err;
|
|
PyObject *res = 0;
|
|
char *assertion_filterstr;
|
|
struct berval ctrl_val;
|
|
LDAP *ld = NULL;
|
|
|
|
if (!PyArg_ParseTuple(args, "s:encode_assertion_control",
|
|
&assertion_filterstr)) {
|
|
goto endlbl;
|
|
}
|
|
|
|
err = ldap_create(&ld);
|
|
if (err != LDAP_SUCCESS)
|
|
return LDAPerror(ld, "ldap_create");
|
|
|
|
err = ldap_create_assertion_control_value(ld,assertion_filterstr,&ctrl_val);
|
|
if (err != LDAP_SUCCESS)
|
|
return LDAPerror(ld, "ldap_create_assertion_control_value");
|
|
|
|
res = LDAPberval_to_object(&ctrl_val);
|
|
|
|
endlbl:
|
|
|
|
return res;
|
|
}
|
|
|
|
static PyMethodDef methods[] = {
|
|
{"encode_page_control", encode_rfc2696, METH_VARARGS },
|
|
{"decode_page_control", decode_rfc2696, METH_VARARGS },
|
|
{"encode_valuesreturnfilter_control", encode_rfc3876, METH_VARARGS },
|
|
{"encode_assertion_control", encode_assertion_control, METH_VARARGS },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void
|
|
LDAPinit_control(PyObject *d)
|
|
{
|
|
LDAPadd_methods(d, methods);
|
|
}
|
|
|
|
|