770611a056
With this commit, all ldap connections accept a new parameter, ``bytes_mode``. When set to ``True``, this flag emulates the old Python 2 behavior, where all fields are bytes - including those declared as UTF-8 by the RFC (DN, RDN, attribute names). If this flag is set to ``False``, the code works with text (unicode) for all text fields (everything except attribute values). If no value is set under Python 2, the code will raise a BytesWarning and proceed with the flag set to ``True``, for backwards compatibility. Under Python 3, the value can only be set to ``False``. For safety and ease of upgrade, the code checks that all provided arguments are of the expected type (unicode with ``bytes_mode=False``, bytes with ``bytes_mode=True``).
279 lines
7.4 KiB
C
279 lines
7.4 KiB
C
/* See http://www.python-ldap.org/ for details.
|
|
* $Id: message.c,v 1.19 2011/10/26 18:38:06 stroeder Exp $ */
|
|
|
|
#include "common.h"
|
|
#include "message.h"
|
|
#include "berval.h"
|
|
#include "errors.h"
|
|
#include "ldapcontrol.h"
|
|
#include "constants.h"
|
|
|
|
/*
|
|
* Converts an LDAP message into a Python structure.
|
|
*
|
|
* On success, returns a list of dictionaries.
|
|
* On failure, returns NULL, and sets an error.
|
|
*
|
|
* The message m is always freed, regardless of return value.
|
|
*
|
|
* If add_ctrls is non-zero, per-entry/referral/partial/intermediate
|
|
* controls will be added as a third item to each entry tuple
|
|
*
|
|
* If add_intermediates is non-zero, intermediate/partial results will
|
|
* be returned
|
|
*/
|
|
PyObject *
|
|
LDAPmessage_to_python(LDAP *ld, LDAPMessage *m, int add_ctrls, int add_intermediates)
|
|
{
|
|
/* we convert an LDAP message into a python structure.
|
|
* It is always a list of dictionaries.
|
|
* We always free m.
|
|
*/
|
|
|
|
PyObject *result, *pyctrls = 0;
|
|
LDAPMessage* entry;
|
|
LDAPControl **serverctrls = 0;
|
|
int rc;
|
|
|
|
result = PyList_New(0);
|
|
if (result == NULL) {
|
|
ldap_msgfree( m );
|
|
return NULL;
|
|
}
|
|
|
|
for(entry = ldap_first_entry(ld,m);
|
|
entry != NULL;
|
|
entry = ldap_next_entry(ld,entry))
|
|
{
|
|
char *dn;
|
|
char *attr;
|
|
BerElement *ber = NULL;
|
|
PyObject* entrytuple;
|
|
PyObject* attrdict;
|
|
PyObject* pydn;
|
|
|
|
dn = ldap_get_dn( ld, entry );
|
|
if (dn == NULL) {
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
return LDAPerror( ld, "ldap_get_dn" );
|
|
}
|
|
pydn = PyUnicode_FromString(dn);
|
|
if (pydn == NULL) {
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(dn);
|
|
return NULL;
|
|
}
|
|
|
|
attrdict = PyDict_New();
|
|
if (attrdict == NULL) {
|
|
Py_DECREF(pydn);
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(dn);
|
|
return NULL;
|
|
}
|
|
|
|
rc = ldap_get_entry_controls( ld, entry, &serverctrls );
|
|
if (rc) {
|
|
Py_DECREF(pydn);
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(dn);
|
|
return LDAPerror( ld, "ldap_get_entry_controls" );
|
|
}
|
|
|
|
/* convert serverctrls to list of tuples */
|
|
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
|
|
int err = LDAP_NO_MEMORY;
|
|
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
|
|
Py_DECREF(pydn);
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(dn);
|
|
ldap_controls_free(serverctrls);
|
|
return LDAPerror( ld, "LDAPControls_to_List" );
|
|
}
|
|
ldap_controls_free(serverctrls);
|
|
|
|
/* Fill attrdict with lists */
|
|
for( attr = ldap_first_attribute( ld, entry, &ber );
|
|
attr != NULL;
|
|
attr = ldap_next_attribute( ld, entry, ber )
|
|
) {
|
|
PyObject* valuelist;
|
|
PyObject* pyattr;
|
|
pyattr = PyUnicode_FromString(attr);
|
|
|
|
struct berval ** bvals =
|
|
ldap_get_values_len( ld, entry, attr );
|
|
|
|
/* Find which list to append to */
|
|
if ( PyDict_Contains( attrdict, pyattr ) ) {
|
|
valuelist = PyDict_GetItem( attrdict, pyattr );
|
|
} else {
|
|
valuelist = PyList_New(0);
|
|
if (valuelist != NULL && PyDict_SetItem(attrdict,
|
|
pyattr, valuelist) == -1) {
|
|
Py_DECREF(valuelist);
|
|
valuelist = NULL; /* catch error later */
|
|
}
|
|
}
|
|
|
|
if (valuelist == NULL) {
|
|
Py_DECREF(pydn);
|
|
Py_DECREF(pyattr);
|
|
Py_DECREF(attrdict);
|
|
Py_DECREF(result);
|
|
if (ber != NULL)
|
|
ber_free(ber, 0);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(attr);
|
|
ldap_memfree(dn);
|
|
Py_XDECREF(pyctrls);
|
|
return NULL;
|
|
}
|
|
|
|
if (bvals != NULL) {
|
|
Py_ssize_t i;
|
|
for (i=0; bvals[i]; i++) {
|
|
PyObject *valuestr;
|
|
|
|
valuestr = LDAPberval_to_object(bvals[i]);
|
|
if (PyList_Append( valuelist, valuestr ) == -1) {
|
|
Py_DECREF(pydn);
|
|
Py_DECREF(pyattr);
|
|
Py_DECREF(attrdict);
|
|
Py_DECREF(result);
|
|
Py_DECREF(valuestr);
|
|
Py_DECREF(valuelist);
|
|
if (ber != NULL)
|
|
ber_free(ber, 0);
|
|
ldap_msgfree( m );
|
|
ldap_memfree(attr);
|
|
ldap_memfree(dn);
|
|
Py_XDECREF(pyctrls);
|
|
return NULL;
|
|
}
|
|
Py_DECREF(valuestr);
|
|
}
|
|
ldap_value_free_len(bvals);
|
|
}
|
|
Py_DECREF(pyattr);
|
|
Py_DECREF( valuelist );
|
|
ldap_memfree(attr);
|
|
}
|
|
|
|
if (add_ctrls) {
|
|
entrytuple = Py_BuildValue("(OOO)", pydn, attrdict, pyctrls);
|
|
} else {
|
|
entrytuple = Py_BuildValue("(OO)", pydn, attrdict);
|
|
}
|
|
Py_DECREF(pydn);
|
|
ldap_memfree(dn);
|
|
Py_DECREF(attrdict);
|
|
Py_XDECREF(pyctrls);
|
|
PyList_Append(result, entrytuple);
|
|
Py_DECREF(entrytuple);
|
|
if (ber != NULL)
|
|
ber_free(ber, 0);
|
|
}
|
|
for(entry = ldap_first_reference(ld,m);
|
|
entry != NULL;
|
|
entry = ldap_next_reference(ld,entry))
|
|
{
|
|
char **refs = NULL;
|
|
PyObject* entrytuple;
|
|
PyObject* reflist = PyList_New(0);
|
|
|
|
if (reflist == NULL) {
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
return NULL;
|
|
}
|
|
if (ldap_parse_reference(ld, entry, &refs, &serverctrls, 0) != LDAP_SUCCESS) {
|
|
Py_DECREF(reflist);
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
return LDAPerror( ld, "ldap_parse_reference" );
|
|
}
|
|
/* convert serverctrls to list of tuples */
|
|
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
|
|
int err = LDAP_NO_MEMORY;
|
|
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
|
|
Py_DECREF(reflist);
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_controls_free(serverctrls);
|
|
return LDAPerror( ld, "LDAPControls_to_List" );
|
|
}
|
|
ldap_controls_free(serverctrls);
|
|
if (refs) {
|
|
Py_ssize_t i;
|
|
for (i=0; refs[i] != NULL; i++) {
|
|
/* A referal is a distinguishedName => unicode */
|
|
PyObject *refstr = PyUnicode_FromString(refs[i]);
|
|
PyList_Append(reflist, refstr);
|
|
Py_DECREF(refstr);
|
|
}
|
|
ber_memvfree( (void **) refs );
|
|
}
|
|
if (add_ctrls) {
|
|
entrytuple = Py_BuildValue("(sOO)", NULL, reflist, pyctrls);
|
|
} else {
|
|
entrytuple = Py_BuildValue("(sO)", NULL, reflist);
|
|
}
|
|
Py_DECREF(reflist);
|
|
Py_XDECREF(pyctrls);
|
|
PyList_Append(result, entrytuple);
|
|
Py_DECREF(entrytuple);
|
|
}
|
|
if (add_intermediates) {
|
|
for(entry = ldap_first_message(ld,m);
|
|
entry != NULL;
|
|
entry = ldap_next_message(ld,entry))
|
|
{
|
|
/* list of tuples */
|
|
/* each tuple is OID, Berval, controllist */
|
|
if ( LDAP_RES_INTERMEDIATE == ldap_msgtype( entry ) ) {
|
|
PyObject* valtuple;
|
|
PyObject *valuestr;
|
|
char *retoid = 0;
|
|
struct berval *retdata = 0;
|
|
|
|
if (ldap_parse_intermediate( ld, entry, &retoid, &retdata, &serverctrls, 0 ) != LDAP_SUCCESS) {
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
return LDAPerror( ld, "ldap_parse_intermediate" );
|
|
}
|
|
/* convert serverctrls to list of tuples */
|
|
if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
|
|
int err = LDAP_NO_MEMORY;
|
|
ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
|
|
Py_DECREF(result);
|
|
ldap_msgfree( m );
|
|
ldap_controls_free(serverctrls);
|
|
ldap_memfree( retoid );
|
|
ber_bvfree( retdata );
|
|
return LDAPerror( ld, "LDAPControls_to_List" );
|
|
}
|
|
ldap_controls_free(serverctrls);
|
|
|
|
valuestr = LDAPberval_to_object(retdata);
|
|
ber_bvfree( retdata );
|
|
valtuple = Py_BuildValue("(sOO)", retoid,
|
|
valuestr ? valuestr : Py_None,
|
|
pyctrls);
|
|
ldap_memfree( retoid );
|
|
Py_DECREF(valuestr);
|
|
Py_XDECREF(pyctrls);
|
|
PyList_Append(result, valtuple);
|
|
Py_DECREF(valtuple);
|
|
}
|
|
}
|
|
}
|
|
ldap_msgfree( m );
|
|
return result;
|
|
}
|