* @copyright 2013 Network RADIUS SARL <info@networkradius.com>
* @copyright 2013 The FreeRADIUS Server Project.
*/
-#include <freeradius-devel/radiusd.h>
-#include <freeradius-devel/modules.h>
-#include <freeradius-devel/rad_assert.h>
-
-#include <stdarg.h>
-#include <ctype.h>
-
-#include <lber.h>
-#include <ldap.h>
-#include "ldap.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <lber.h>
+#include <ldap.h>
+#include "ldap.h"
/** Converts "bad" strings into ones which are safe for LDAP
*
goto process_error;
}
- process_error:
-
+process_error:
if ((lib_errno == LDAP_SUCCESS) && (srv_errno != LDAP_SUCCESS)) {
lib_errno = srv_errno;
} else if ((lib_errno != LDAP_SUCCESS) && (srv_errno == LDAP_SUCCESS)) {
return status; /* caller closes the connection */
}
-
/** Search for something in the LDAP directory
*
* Binds as the administrative user and performs a search, dealing with any errors.
switch (status) {
case LDAP_PROC_SUCCESS:
break;
+
case LDAP_PROC_RETRY:
*pconn = fr_connection_reconnect(inst->pool, *pconn);
if (*pconn) {
if (radius_xlat(filter, sizeof(filter), request, inst->userobj_filter, rlm_ldap_escape_func, NULL) < 0) {
REDEBUG("Unable to create filter");
-
*rcode = RLM_MODULE_INVALID;
+
return NULL;
}
if (radius_xlat(base_dn, sizeof(base_dn), request, inst->userobj_base_dn, rlm_ldap_escape_func, NULL) < 0) {
REDEBUG("Unable to create base_dn");
-
*rcode = RLM_MODULE_INVALID;
+
return NULL;
}
switch (status) {
case LDAP_PROC_SUCCESS:
break;
+
case LDAP_PROC_NO_RESULT:
*rcode = RLM_MODULE_NOTFOUND;
return NULL;
+
default:
*rcode = RLM_MODULE_FAIL;
return NULL;
}
#endif
+/** Close and delete a connection
+ *
+ * Unbinds the LDAP connection, informing the server and freeing any memory, then releases the memory used by the
+ * connection handle.
+ *
+ * @param conn to destroy.
+ * @return always indicates success.
+ */
+static int _mod_conn_free(ldap_handle_t *conn)
+{
+ if (conn->handle) {
+ DEBUG3("rlm_ldap: Closing libldap handle %p", conn->handle);
+ ldap_unbind_s(conn->handle);
+ }
+
+ return 0;
+}
+
/** Create and return a new connection
*
* Create a new ldap connection and allocate memory for a new rlm_handle_t
- *
- * @param instance rlm_ldap instance.
- * @return A new connection handle or NULL on error.
*/
-void *mod_conn_create(void *instance)
+void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
{
ldap_rcode_t status;
/*
* Allocate memory for the handle.
*/
- conn = talloc_zero(instance, ldap_handle_t);
+ conn = talloc_zero(ctx, ldap_handle_t);
if (!conn) return NULL;
+ talloc_set_destructor(conn, _mod_conn_free);
conn->inst = inst;
conn->rebound = false;
goto error;
}
}
+ DEBUG3("rlm_ldap: New libldap handle %p", conn->handle);
/*
* We now have a connection structure, but no actual TCP connection.
}
/*
+ * Leave "dereference" unset to use the OpenLDAP default.
+ */
+ if (inst->dereference_str) {
+ do_ldap_option(LDAP_OPT_DEREF, "dereference", &(inst->dereference));
+ }
+
+ /*
* Leave "chase_referrals" unset to use the OpenLDAP default.
*/
if (!inst->chase_referrals_unset) {
}
}
- memset(&tv, 0, sizeof(tv));
- tv.tv_sec = inst->net_timeout;
+#ifdef LDAP_OPT_NETWORK_TIMEOUT
+ if (inst->net_timeout) {
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = inst->net_timeout;
- do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
+ do_ldap_option(LDAP_OPT_NETWORK_TIMEOUT, "net_timeout", &tv);
+ }
+#endif
do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(inst->srv_timelimit));
return conn;
- error:
- if (conn->handle) ldap_unbind_s(conn->handle);
+error:
talloc_free(conn);
return NULL;
}
-
-/** Close and delete a connection
- *
- * Unbinds the LDAP connection, informing the server and freeing any memory, then releases the memory used by the
- * connection handle.
- *
- * @param instance rlm_ldap instance.
- * @param handle to destroy.
- * @return always indicates success.
- */
-int mod_conn_delete(UNUSED void *instance, void *handle)
-{
- ldap_handle_t *conn = handle;
-
- ldap_unbind_s(conn->handle);
- talloc_free(conn);
-
- return 0;
-}
-
-
/** Gets an LDAP socket from the connection pool
*
* Retrieve a socket from the connection pool, or NULL on error (of if no sockets are available).
return fr_connection_get(inst->pool);
}
-
/** Frees an LDAP socket back to the connection pool
*
* If the socket was rebound chasing a referral onto another server then we destroy it.