Skip to content

Commit

Permalink
Attach msgid/controls/... to exceptions (Closes #177, #208)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondřej Kuzník committed May 7, 2020
1 parent 7d92e0f commit f754e35
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 23 deletions.
3 changes: 1 addition & 2 deletions Modules/LDAPObject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1172,9 +1172,8 @@ l_ldap_result4(LDAPObject *self, PyObject *args)
else
e = "ldap_parse_result";
ldap_controls_free(serverctrls);
ldap_msgfree(msg);
Py_XDECREF(valuestr);
return LDAPerror(self->ldap, e);
return LDAPraise_for_message(self->ldap, e, msg);
}

if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
Expand Down
110 changes: 89 additions & 21 deletions Modules/constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "common.h"
#include "constants.h"
#include "ldapcontrol.h"
#include "lber.h"
#include "ldap.h"

Expand Down Expand Up @@ -48,38 +49,81 @@ LDAPerr(int errnum)

/* Convert an LDAP error into an informative python exception */
PyObject *
LDAPerror(LDAP *l, char *msg)
LDAPraise_for_message(LDAP *l, char *msg, LDAPMessage *m)
{
if (l == NULL) {
PyErr_SetFromErrno(LDAPexception_class);
ldap_msgfree(m);
return NULL;
}
else {
int myerrno, errnum, opt_errnum;
int myerrno, errnum, opt_errnum, msgid = -1, msgtype = 0;
PyObject *errobj;
PyObject *info;
PyObject *str;
PyObject *pyerrno;
char *matched, *error;
PyObject *pyresult;
PyObject *pyctrls = NULL;
char *matched = NULL,
*error = NULL,
**refs = NULL;
LDAPControl **serverctrls = NULL;

/* at first save errno for later use before it gets overwritten by another call */
myerrno = errno;

opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
if (opt_errnum != LDAP_OPT_SUCCESS)
errnum = opt_errnum;
if (m != NULL) {
msgid = ldap_msgid(m);
msgtype = ldap_msgtype(m);
ldap_parse_result(l, m, &errnum, &matched, &error, &refs,
&serverctrls, 1);
}

if (errnum == LDAP_NO_MEMORY)
return PyErr_NoMemory();
if (msgtype <= 0) {
opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
if (opt_errnum != LDAP_OPT_SUCCESS)
errnum = opt_errnum;

if (errnum == LDAP_NO_MEMORY) {
return PyErr_NoMemory();
}

ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched);
ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error);
}

if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
errobj = errobjects[errnum + LDAP_ERROR_OFFSET];
else
errobj = LDAPexception_class;

info = PyDict_New();
if (info == NULL)
if (info == NULL) {
ldap_memfree(matched);
ldap_memfree(error);
ldap_memvfree((void **)refs);
ldap_controls_free(serverctrls);
return NULL;
}

if (msgtype > 0) {
pyresult = PyInt_FromLong(msgtype);
if (pyresult)
PyDict_SetItemString(info, "msgtype", pyresult);
Py_XDECREF(pyresult);
}

if (msgid >= 0) {
pyresult = PyInt_FromLong(msgid);
if (pyresult)
PyDict_SetItemString(info, "msgid", pyresult);
Py_XDECREF(pyresult);
}

pyresult = PyInt_FromLong(errnum);
if (pyresult)
PyDict_SetItemString(info, "result", pyresult);
Py_XDECREF(pyresult);

str = PyUnicode_FromString(ldap_err2string(errnum));
if (str)
Expand All @@ -93,8 +137,21 @@ LDAPerror(LDAP *l, char *msg)
Py_XDECREF(pyerrno);
}

if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0
&& matched != NULL) {
if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
int err = LDAP_NO_MEMORY;

ldap_set_option(l, LDAP_OPT_ERROR_NUMBER, &err);
ldap_memfree(matched);
ldap_memfree(error);
ldap_memvfree((void **)refs);
ldap_controls_free(serverctrls);
return PyErr_NoMemory();
}
ldap_controls_free(serverctrls);
PyDict_SetItemString(info, "ctrls", pyctrls);
Py_XDECREF(pyctrls);

if (matched != NULL) {
if (*matched != '\0') {
str = PyUnicode_FromString(matched);
if (str)
Expand All @@ -104,27 +161,38 @@ LDAPerror(LDAP *l, char *msg)
ldap_memfree(matched);
}

if (errnum == LDAP_REFERRAL) {
if (errnum == LDAP_REFERRAL && refs != NULL && refs[0] != NULL) {
/* Keep old behaviour, overshadow error message */
char err[1024];

snprintf(err, sizeof(err), "Referral:\n%s", refs[0]);
str = PyUnicode_FromString(err);
PyDict_SetItemString(info, "info", str);
Py_XDECREF(str);
}
else if (msg != NULL || (error != NULL && *error != '\0')) {
msg = msg ? msg : error;

str = PyUnicode_FromString(msg);
if (str)
PyDict_SetItemString(info, "info", str);
Py_XDECREF(str);
}
else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) {
if (error != NULL && *error != '\0') {
str = PyUnicode_FromString(error);
if (str)
PyDict_SetItemString(info, "info", str);
Py_XDECREF(str);
}
ldap_memfree(error);
}

PyErr_SetObject(errobj, info);
Py_DECREF(info);
ldap_memvfree((void **)refs);
ldap_memfree(error);
return NULL;
}
}

PyObject *
LDAPerror(LDAP *l, char *msg)
{
return LDAPraise_for_message(l, msg, NULL);
}

/* initialise the module constants */

int
Expand Down
1 change: 1 addition & 0 deletions Modules/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extern PyObject *LDAPconstant(int);

extern PyObject *LDAPexception_class;
extern PyObject *LDAPerror(LDAP *, char *msg);
extern PyObject *LDAPraise_for_message(LDAP *, char *msg, LDAPMessage *m);
PyObject *LDAPerr(int errnum);

#ifndef LDAP_CONTROL_PAGE_OID
Expand Down

0 comments on commit f754e35

Please sign in to comment.