]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Split configurations in rlm_ldap into instance and pool specific
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 29 Nov 2016 22:04:48 +0000 (17:04 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 29 Nov 2016 22:04:48 +0000 (17:04 -0500)
src/modules/rlm_ldap/clients.c
src/modules/rlm_ldap/directory.c
src/modules/rlm_ldap/ldap.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_ldap/rlm_ldap.h

index a549a4c7ee8fe45f70385c4f89054f6bc19b4177..123dd2a517dad3c563cbd68c527e145bfb0d7172 100644 (file)
@@ -145,8 +145,9 @@ int rlm_ldap_client_load(rlm_ldap_t const *inst, CONF_SECTION *tmpl, CONF_SECTIO
         *      Perform all searches as the admin user.
         */
        if (conn->rebound) {
-               status = rlm_ldap_bind(inst, NULL, &conn, conn->inst->admin_identity, conn->inst->admin_password,
-                                      &(conn->inst->admin_sasl), true, NULL, NULL, NULL);
+               status = rlm_ldap_bind(inst, NULL, &conn,
+                                      conn->pool_inst->admin_identity, conn->pool_inst->admin_password,
+                                      &(conn->pool_inst->admin_sasl), true, NULL, NULL, NULL);
                if (status != LDAP_PROC_SUCCESS) {
                        ret = -1;
                        goto finish;
index 0e4776b79df461fff7240d162726ec309fdb58b3..34b0075bacfa6b1321ce7e0df8dbbb1048693ebd 100644 (file)
@@ -56,7 +56,7 @@ static FR_NAME_NUMBER const ldap_directory_type_table[] = {
  *     - 1 if we failed identifying the directory server.
  *     - -1 on error.
  */
-int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t *inst, ldap_handle_t **pconn)
+int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t const *inst, ldap_handle_t **pconn)
 {
        static char const       *attrs[] = { "vendorname",
                                             "vendorversion",
@@ -115,7 +115,7 @@ int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t
 
        values = ldap_get_values_len((*pconn)->handle, entry, "vendorname");
        if (values) {
-               directory->vendor_str = rlm_ldap_berval_to_string(inst, values[0]);
+               directory->vendor_str = rlm_ldap_berval_to_string(directory, values[0]);
                INFO("Directory vendor: %s", directory->vendor_str);
 
                ldap_value_free_len(values);
@@ -123,7 +123,7 @@ int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t
 
        values = ldap_get_values_len((*pconn)->handle, entry, "vendorversion");
        if (values) {
-               directory->version_str = rlm_ldap_berval_to_string(inst, values[0]);
+               directory->version_str = rlm_ldap_berval_to_string(directory, values[0]);
                INFO("Directory version: %s", directory->version_str);
 
                ldap_value_free_len(values);
index bd4e81252692021dd8d2a698a37cf0e99032f326..51da42431edf3c66d9c831d2645994d5fa80ecaf 100644 (file)
@@ -921,7 +921,8 @@ ldap_rcode_t rlm_ldap_bind(rlm_ldap_t const *inst,
                                *pconn = fr_connection_reconnect(inst->pool, request, *pconn);
                                if (*pconn) {
                                        ROPTIONAL(RWDEBUG, WARN, "Bind with %s to %s failed: %s. Got new socket, "
-                                                 "retrying...", *dn ? dn : "(anonymous)", inst->server, error);
+                                                 "retrying...", *dn ? dn : "(anonymous)",
+                                                 (*pconn)->pool_inst->server, error);
 
                                        talloc_free(extra); /* don't leak debug info */
 
@@ -937,7 +938,7 @@ ldap_rcode_t rlm_ldap_bind(rlm_ldap_t const *inst,
                        /* FALL-THROUGH */
                default:
                        ROPTIONAL(REDEBUG, ERROR, "Bind with %s to %s failed: %s", *dn ? dn : "(anonymous)",
-                                 inst->server, error);
+                                 (*pconn)->pool_inst->server, error);
                        LDAP_EXTRA_DEBUG();
 
                        break;
@@ -1020,8 +1021,8 @@ ldap_rcode_t rlm_ldap_search(LDAPMessage **result, rlm_ldap_t const *inst, REQUE
         *      Do all searches as the admin user.
         */
        if ((*pconn)->rebound) {
-               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
-                                      (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+                                      (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
                                       NULL, NULL, NULL);
                if (status != LDAP_PROC_SUCCESS) {
                        return LDAP_PROC_ERROR;
@@ -1183,8 +1184,8 @@ ldap_rcode_t rlm_ldap_modify(rlm_ldap_t const *inst, REQUEST *request, ldap_hand
         *      Perform all modifications as the admin user.
         */
        if ((*pconn)->rebound) {
-               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
-                                      (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+                                      (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
                                       NULL, NULL, NULL);
                if (status != LDAP_PROC_SUCCESS) {
                        return LDAP_PROC_ERROR;
@@ -1313,8 +1314,8 @@ char const *rlm_ldap_find_user(rlm_ldap_t const *inst, REQUEST *request, ldap_ha
         *      Perform all searches as the admin user.
         */
        if ((*pconn)->rebound) {
-               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->inst->admin_identity,
-                                      (*pconn)->inst->admin_password, &(*pconn)->inst->admin_sasl, true,
+               status = rlm_ldap_bind(inst, request, pconn, (*pconn)->pool_inst->admin_identity,
+                                      (*pconn)->pool_inst->admin_password, &(*pconn)->pool_inst->admin_sasl, true,
                                       NULL, NULL, NULL);
                if (status != LDAP_PROC_SUCCESS) {
                        *rcode = RLM_MODULE_FAIL;
@@ -1475,7 +1476,7 @@ rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, REQUEST *request,
  * @param inst rlm_ldap configuration.
  * @param request Current request.
  */
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request)
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn)
 {
        /*
        *       More warning messages for people who can't be bothered to read the documentation.
@@ -1490,7 +1491,7 @@ void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request)
            !fr_pair_find_by_num(request->control, 0, PW_USER_PASSWORD, TAG_ANY) &&
            !fr_pair_find_by_num(request->control, 0, PW_PASSWORD_WITH_HEADER, TAG_ANY) &&
            !fr_pair_find_by_num(request->control, 0, PW_CRYPT_PASSWORD, TAG_ANY)) {
-               switch (inst->directory->type) {
+               switch (conn->directory->type) {
                case LDAP_DIRECTORY_ACTIVE_DIRECTORY:
                        RWDEBUG("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
                        RWDEBUG("!!! Active Directory does not allow passwords to be read via LDAP");
@@ -1521,13 +1522,13 @@ void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request)
                        break;
 
                default:
-                       if (!inst->admin_identity) {
+                       if (!conn->pool_inst->admin_identity) {
                                RWDEBUG("!!! Found map between LDAP attribute and a FreeRADIUS password attribute");
                                RWDEBUG("!!! but no password attribute found in search result");
                                RWDEBUG("!!! Either:");
                                RWDEBUG("!!!  - Ensure the user object contains a password attribute, and that ");
                                RWDEBUG("!!!    \"%s\" has permission to read that password attribute (recommended)",
-                                       inst->admin_identity);
+                                       conn->pool_inst->admin_identity);
                                RWDEBUG("!!!  - Bind as the user by listing %s in the authenticate section, and",
                                        inst->name);
                                RWDEBUG("!!!    setting attribute &control:Auth-Type := '%s' in the authorize section",
@@ -1565,14 +1566,15 @@ void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request)
 static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t request, UNUSED ber_int_t msgid,
                           void *ctx)
 {
-       ldap_rcode_t            status;
-       ldap_handle_t           *conn = talloc_get_type_abort(ctx, ldap_handle_t);
-       rlm_ldap_t const        *inst = conn->inst;
+       ldap_rcode_t                    status;
+       ldap_handle_t                   *conn = talloc_get_type_abort(ctx, ldap_handle_t);
+       ldap_pool_inst_t const          *pool_inst = conn->pool_inst;
+       rlm_ldap_t const                *inst = conn->inst;
 
-       char const              *admin_identity = NULL;
-       char const              *admin_password = NULL;
+       char const                      *admin_identity = NULL;
+       char const                      *admin_password = NULL;
 
-       int                     ldap_errno;
+       int                             ldap_errno;
 
        conn->referred = true;
        conn->rebound = true;   /* not really, but oh well... */
@@ -1586,7 +1588,7 @@ static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t
         *      SASL mech is inherited from the module that defined the connection
         *      pool.
         */
-       if (inst->use_referral_credentials) {
+       if (pool_inst->use_referral_credentials) {
                LDAPURLDesc     *ldap_url;
                int             ret;
                char            **ext;
@@ -1649,12 +1651,12 @@ static int rlm_ldap_rebind(LDAP *handle, LDAP_CONST char *url, UNUSED ber_tag_t
        } else
 #  endif
        {
-               admin_identity = conn->inst->admin_identity;
-               admin_password = conn->inst->admin_password;
+               admin_identity = pool_inst->admin_identity;
+               admin_password = pool_inst->admin_password;
        }
 
        status = rlm_ldap_bind(inst, NULL, &conn, admin_identity, admin_password,
-                              &conn->inst->admin_sasl, false, NULL, NULL, NULL);
+                              &conn->pool_inst->admin_sasl, false, NULL, NULL, NULL);
        if (status != LDAP_PROC_SUCCESS) {
                ldap_get_option(handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
 
@@ -1746,19 +1748,20 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
 
        int ldap_errno, ldap_version;
 
-       rlm_ldap_t      *inst = instance;
-       ldap_handle_t   *conn;
-       LDAP            *handle = NULL;
+       rlm_ldap_t const        *inst = talloc_get_type_abort(instance, rlm_ldap_t);
+       ldap_pool_inst_t const  *pool_inst = &inst->pool_inst;
+       ldap_handle_t           *conn;
+       LDAP                    *handle = NULL;
 
-       DEBUG("Connecting to %s", inst->server);
+       DEBUG("Connecting to %s", pool_inst->server);
 #ifdef HAVE_LDAP_INITIALIZE
-       ldap_errno = ldap_initialize(&handle, inst->server);
+       ldap_errno = ldap_initialize(&handle, pool_inst->server);
        if (ldap_errno != LDAP_SUCCESS) {
                ERROR("ldap_initialize failed: %s", ldap_err2string(ldap_errno));
                return NULL;
        }
 #else
-       handle = ldap_init(inst->server, inst->port);
+       handle = ldap_init(pool_inst->server, pool_inst->port);
        if (!handle) {
                ERROR("ldap_init failed");
                return NULL;
@@ -1771,7 +1774,7 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
        conn = talloc_zero(ctx, ldap_handle_t);
        if (!conn) return NULL;
 
-       conn->inst = inst;
+       conn->pool_inst = pool_inst;
        conn->handle = handle;
        conn->rebound = false;
        conn->referred = false;
@@ -1798,18 +1801,18 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
        /*
         *      Leave "dereference" unset to use the OpenLDAP default.
         */
-       if (inst->dereference_str) {
-               do_ldap_option(LDAP_OPT_DEREF, "dereference", &(inst->dereference));
+       if (pool_inst->dereference_str) {
+               do_ldap_option(LDAP_OPT_DEREF, "dereference", &(pool_inst->dereference));
        }
 
        /*
         *      Leave "chase_referrals" unset to use the OpenLDAP default.
         */
-       if (!inst->chase_referrals_unset) {
-               if (inst->chase_referrals) {
+       if (!pool_inst->chase_referrals_unset) {
+               if (pool_inst->chase_referrals) {
                        do_ldap_option(LDAP_OPT_REFERRALS, "chase_referrals", LDAP_OPT_ON);
 
-                       if (inst->rebind == true) {
+                       if (pool_inst->rebind == true) {
 #if LDAP_SET_REBIND_PROC_ARGS == 3
                                ldap_set_rebind_proc(conn->handle, rlm_ldap_rebind, conn);
 #endif
@@ -1821,7 +1824,7 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
 
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
        /*
-        *      A value of zero results in an instant failure.
+        *      A value of zero results in an pool_instant failure.
         *
         *      When most people specify zero they mean infinite.
         *
@@ -1836,41 +1839,41 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
        }
 #endif
 
-       do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(inst->srv_timelimit));
+       do_ldap_option(LDAP_OPT_TIMELIMIT, "srv_timelimit", &(pool_inst->srv_timelimit));
 
        ldap_version = LDAP_VERSION3;
        do_ldap_option(LDAP_OPT_PROTOCOL_VERSION, "ldap_version", &ldap_version);
 
 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
-       do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive_idle", &(inst->keepalive_idle));
+       do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE, "keepalive_idle", &(pool_inst->keepalive_idle));
 #endif
 
 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
-       do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive_probes", &(inst->keepalive_probes));
+       do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES, "keepalive_probes", &(pool_inst->keepalive_probes));
 #endif
 
 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
-       do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive_interval", &(inst->keepalive_interval));
+       do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL, "keepalive_interval", &(pool_inst->keepalive_interval));
 #endif
 
 #ifdef HAVE_LDAP_START_TLS_S
        /*
         *      Set all of the TLS options
         */
-       if (inst->tls_mode) do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(inst->tls_mode));
+       if (pool_inst->tls_mode) do_ldap_option(LDAP_OPT_X_TLS, "tls_mode", &(pool_inst->tls_mode));
 
-       maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", inst->tls_ca_file);
-       maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", inst->tls_ca_path);
+       maybe_ldap_option(LDAP_OPT_X_TLS_CACERTFILE, "ca_file", pool_inst->tls_ca_file);
+       maybe_ldap_option(LDAP_OPT_X_TLS_CACERTDIR, "ca_path", pool_inst->tls_ca_path);
 
        /*
         *      Set certificate options
         */
-       maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", inst->tls_certificate_file);
-       maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", inst->tls_private_key_file);
+       maybe_ldap_option(LDAP_OPT_X_TLS_CERTFILE, "certificate_file", pool_inst->tls_certificate_file);
+       maybe_ldap_option(LDAP_OPT_X_TLS_KEYFILE, "private_key_file", pool_inst->tls_private_key_file);
 
 #  ifdef LDAP_OPT_X_TLS_NEVER
-       if (inst->tls_require_cert_str) {
-               do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &inst->tls_require_cert);
+       if (pool_inst->tls_require_cert_str) {
+               do_ldap_option(LDAP_OPT_X_TLS_REQUIRE_CERT, "require_cert", &pool_inst->tls_require_cert);
        }
 #  endif
 
@@ -1889,8 +1892,8 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
        /*
         *      And finally start the TLS code.
         */
-       if (inst->start_tls) {
-               if (inst->port == 636) {
+       if (pool_inst->start_tls) {
+               if (pool_inst->port == 636) {
                        WARN("Told to Start TLS on LDAPS port this will probably fail, please correct the "
                             "configuration");
                }
@@ -1904,25 +1907,14 @@ void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *tim
        }
 #endif /* HAVE_LDAP_START_TLS_S */
 
-       status = rlm_ldap_bind(inst, NULL, &conn, conn->inst->admin_identity, conn->inst->admin_password,
-                              &(conn->inst->admin_sasl), false, timeout, NULL, NULL);
+       status = rlm_ldap_bind(inst, NULL, &conn, conn->pool_inst->admin_identity, conn->pool_inst->admin_password,
+                              &(conn->pool_inst->admin_sasl), false, timeout, NULL, NULL);
        if (status != LDAP_PROC_SUCCESS) goto error;
 
        /*
-        *      This allows multiple connections to spawn simultaneously,
-        *      but prevents them being used until we've directory
-        *      directory capabilities.
+        *      Only error out on memory allocation errors
         */
-       if (!inst->directory) {
-               pthread_mutex_lock(&inst->directory_mutex);
-               if (!inst->directory) {
-                       /*
-                        *      Only error out on memory allocation errors
-                        */
-                       if (rlm_ldap_directory_alloc(NULL, &inst->directory, inst, &conn) < 0) goto error;
-                       pthread_mutex_unlock(&inst->directory_mutex);
-               }
-       }
+       if (rlm_ldap_directory_alloc(conn, &conn->directory, inst, &conn) < 0) goto error;
 
        return conn;
 
index 6e1feb4d718667545c9b11482c2d84249848b371..dc1b78f759af9a6ed35c4e6bf51e8e7712012724 100644 (file)
@@ -93,21 +93,21 @@ static CONF_PARSER tls_config[] = {
        /*
         *      Deprecated attributes
         */
-       { FR_CONF_OFFSET("ca_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_ca_file) },
+       { FR_CONF_OFFSET("ca_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_ca_file) },
 
-       { FR_CONF_OFFSET("ca_path", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_ca_path) },
+       { FR_CONF_OFFSET("ca_path", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_ca_path) },
 
-       { FR_CONF_OFFSET("certificate_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_certificate_file) },
+       { FR_CONF_OFFSET("certificate_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_certificate_file) },
 
-       { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_private_key_file) },
-
-       { FR_CONF_OFFSET("random_file", PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file) },
+       { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, ldap_pool_inst_t, tls_private_key_file) },
 
        /*
         *      LDAP Specific TLS attributes
         */
-       { FR_CONF_OFFSET("start_tls", PW_TYPE_BOOLEAN, rlm_ldap_t, start_tls), .dflt = "no" },
-       { FR_CONF_OFFSET("require_cert", PW_TYPE_STRING, rlm_ldap_t, tls_require_cert_str) },
+       { FR_CONF_OFFSET("start_tls", PW_TYPE_BOOLEAN, ldap_pool_inst_t, start_tls), .dflt = "no" },
+
+       { FR_CONF_OFFSET("require_cert", PW_TYPE_STRING, ldap_pool_inst_t, tls_require_cert_str) },
+
        CONF_PARSER_TERMINATOR
 };
 
@@ -176,54 +176,67 @@ static const CONF_PARSER acct_section_config[] = {
  */
 static CONF_PARSER option_config[] = {
        /*
-        *      Debugging flags to the server
+        *      Pool config items
         */
-       { FR_CONF_OFFSET("ldap_debug", PW_TYPE_INTEGER, rlm_ldap_t, ldap_debug), .dflt = "0x0000" },
-
-       { FR_CONF_OFFSET("dereference", PW_TYPE_STRING, rlm_ldap_t, dereference_str) },
+       { FR_CONF_OFFSET("chase_referrals", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.chase_referrals) },
 
-       { FR_CONF_OFFSET("chase_referrals", PW_TYPE_BOOLEAN, rlm_ldap_t, chase_referrals) },
+       { FR_CONF_OFFSET("use_referral_credentials", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.use_referral_credentials), .dflt = "no" },
 
-       { FR_CONF_OFFSET("use_referral_credentials", PW_TYPE_BOOLEAN, rlm_ldap_t, use_referral_credentials), .dflt = "no" },
-
-       { FR_CONF_OFFSET("rebind", PW_TYPE_BOOLEAN, rlm_ldap_t, rebind) },
+       { FR_CONF_OFFSET("rebind", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.rebind) },
 
 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
-       { FR_CONF_OFFSET("session_tracking", PW_TYPE_BOOLEAN, rlm_ldap_t, session_tracking), .dflt = "no" },
+       { FR_CONF_OFFSET("session_tracking", PW_TYPE_BOOLEAN, rlm_ldap_t, pool_inst.session_tracking), .dflt = "no" },
 #endif
 
 #ifdef LDAP_OPT_NETWORK_TIMEOUT
        /* timeout on network activity */
-       { FR_CONF_DEPRECATED("net_timeout", PW_TYPE_INTEGER, rlm_ldap_t, net_timeout), .dflt = "10" },
+       { FR_CONF_DEPRECATED("net_timeout", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.net_timeout), .dflt = "10" },
 #endif
 
-       /* timeout for search results */
-       { FR_CONF_OFFSET("res_timeout", PW_TYPE_INTEGER, rlm_ldap_t, res_timeout), .dflt = "20" },
-
-       /* allow server unlimited time for search (server-side limit) */
-       { FR_CONF_OFFSET("srv_timelimit", PW_TYPE_INTEGER, rlm_ldap_t, srv_timelimit), .dflt = "20" },
-
 #ifdef LDAP_OPT_X_KEEPALIVE_IDLE
-       { FR_CONF_OFFSET("idle", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_idle), .dflt = "60" },
+       { FR_CONF_OFFSET("idle", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_idle), .dflt = "60" },
 #endif
 #ifdef LDAP_OPT_X_KEEPALIVE_PROBES
-       { FR_CONF_OFFSET("probes", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_probes), .dflt = "3" },
+       { FR_CONF_OFFSET("probes", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_probes), .dflt = "3" },
 #endif
 #ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
-       { FR_CONF_OFFSET("interval", PW_TYPE_INTEGER, rlm_ldap_t, keepalive_interval), .dflt = "30" },
+       { FR_CONF_OFFSET("interval", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.keepalive_interval), .dflt = "30" },
 #endif
+
+       { FR_CONF_OFFSET("dereference", PW_TYPE_STRING, rlm_ldap_t, pool_inst.dereference_str) },
+
+       /* allow server unlimited time for search (server-side limit) */
+       { FR_CONF_OFFSET("srv_timelimit", PW_TYPE_INTEGER, rlm_ldap_t, pool_inst.srv_timelimit), .dflt = "20" },
+
+       /*
+        *      Instance config items
+        */
+       /* timeout for search results */
+       { FR_CONF_OFFSET("res_timeout", PW_TYPE_INTEGER, rlm_ldap_t, res_timeout), .dflt = "20" },
+
        CONF_PARSER_TERMINATOR
 };
 
+static const CONF_PARSER global_config[] = {
+       { FR_CONF_OFFSET("random_file", PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file) },
+
+       { FR_CONF_OFFSET("ldap_debug", PW_TYPE_INTEGER, rlm_ldap_t, ldap_debug), .dflt = "0x0000" },            /* Debugging flags to the server */
+
+       CONF_PARSER_TERMINATOR
+};
 
 static const CONF_PARSER module_config[] = {
-       { FR_CONF_OFFSET("server", PW_TYPE_STRING | PW_TYPE_MULTI, rlm_ldap_t, config_server) },        /* Do not set to required */
-       { FR_CONF_OFFSET("port", PW_TYPE_SHORT, rlm_ldap_t, port) },
+       /*
+        *      Pool config items
+        */
+       { FR_CONF_OFFSET("server", PW_TYPE_STRING | PW_TYPE_MULTI, rlm_ldap_t, pool_inst.config_server) },      /* Do not set to required */
+
+       { FR_CONF_OFFSET("port", PW_TYPE_SHORT, rlm_ldap_t, pool_inst.port) },
 
-       { FR_CONF_OFFSET("identity", PW_TYPE_STRING, rlm_ldap_t, admin_identity) },
-       { FR_CONF_OFFSET("password", PW_TYPE_STRING | PW_TYPE_SECRET, rlm_ldap_t, admin_password) },
+       { FR_CONF_OFFSET("identity", PW_TYPE_STRING, rlm_ldap_t, pool_inst.admin_identity) },
+       { FR_CONF_OFFSET("password", PW_TYPE_STRING | PW_TYPE_SECRET, rlm_ldap_t, pool_inst.admin_password) },
 
-       { FR_CONF_OFFSET("sasl", PW_TYPE_SUBSECTION, rlm_ldap_t, admin_sasl), .subcs = (void const *) sasl_mech_static },
+       { FR_CONF_OFFSET("sasl", PW_TYPE_SUBSECTION, rlm_ldap_t, pool_inst.admin_sasl), .subcs = (void const *) sasl_mech_static },
 
        { FR_CONF_OFFSET("valuepair_attribute", PW_TYPE_STRING, rlm_ldap_t, valuepair_attr) },
 
@@ -250,7 +263,9 @@ static const CONF_PARSER module_config[] = {
 
        { FR_CONF_POINTER("options", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) option_config },
 
-       { FR_CONF_POINTER("tls", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) tls_config },
+       { FR_CONF_POINTER("global", PW_TYPE_SUBSECTION, NULL), .subcs = (void const *) global_config },
+
+       { FR_CONF_OFFSET("tls", PW_TYPE_SUBSECTION, rlm_ldap_t, pool_inst), .subcs = (void const *) tls_config },
        CONF_PARSER_TERMINATOR
 };
 
@@ -689,28 +704,28 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
        /*
         *      Expand dynamic SASL fields
         */
-       if (conn->inst->user_sasl.mech) {
+       if (inst->user_sasl.mech) {
                memset(&sasl, 0, sizeof(sasl));
 
                if (tmpl_expand(&sasl.mech, sasl_mech_buff, sizeof(sasl_mech_buff), request,
-                               conn->inst->user_sasl.mech, rlm_ldap_escape_func, inst) < 0) {
+                               inst->user_sasl.mech, rlm_ldap_escape_func, inst) < 0) {
                        REDEBUG("Failed expanding user.sasl.mech: %s", fr_strerror());
                        rcode = RLM_MODULE_FAIL;
                        goto finish;
                }
 
-               if (conn->inst->user_sasl.proxy) {
+               if (inst->user_sasl.proxy) {
                        if (tmpl_expand(&sasl.proxy, sasl_proxy_buff, sizeof(sasl_proxy_buff), request,
-                                       conn->inst->user_sasl.proxy, rlm_ldap_escape_func, inst) < 0) {
+                                       inst->user_sasl.proxy, rlm_ldap_escape_func, inst) < 0) {
                                REDEBUG("Failed expanding user.sasl.proxy: %s", fr_strerror());
                                rcode = RLM_MODULE_FAIL;
                                goto finish;
                        }
                }
 
-               if (conn->inst->user_sasl.realm) {
+               if (inst->user_sasl.realm) {
                        if (tmpl_expand(&sasl.realm, sasl_realm_buff, sizeof(sasl_realm_buff), request,
-                                       conn->inst->user_sasl.realm, rlm_ldap_escape_func, inst) < 0) {
+                                       inst->user_sasl.realm, rlm_ldap_escape_func, inst) < 0) {
                                REDEBUG("Failed expanding user.sasl.realm: %s", fr_strerror());
                                rcode = RLM_MODULE_FAIL;
                                goto finish;
@@ -731,7 +746,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, UNUSED void
        }
        conn->rebound = true;
        status = rlm_ldap_bind(inst, request, &conn, dn, request->password->vp_strvalue,
-                              conn->inst->user_sasl.mech ? &sasl : NULL, true, NULL, NULL, NULL);
+                              inst->user_sasl.mech ? &sasl : NULL, true, NULL, NULL, NULL);
        switch (status) {
        case LDAP_PROC_SUCCESS:
                rcode = RLM_MODULE_OK;
@@ -1066,7 +1081,7 @@ skip_edir:
                RINDENT();
                if (rlm_ldap_map_do(inst, request, conn->handle, &expanded, entry) > 0) rcode = RLM_MODULE_UPDATED;
                REXDENT();
-               rlm_ldap_check_reply(inst, request);
+               rlm_ldap_check_reply(inst, request, conn);
        }
 
 finish:
@@ -1341,11 +1356,8 @@ static int mod_detach(void *instance)
        if (inst->userobj_sort_ctrl) ldap_control_free(inst->userobj_sort_ctrl);
 #endif
 
-       pthread_mutex_destroy(&inst->directory_mutex);
-
        fr_connection_pool_free(inst->pool);
        talloc_free(inst->user_map);
-       talloc_free(inst->directory);
 
        return 0;
 }
@@ -1473,7 +1485,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
 
        options = cf_section_sub_find(conf, "options");
        if (!options || !cf_pair_find(options, "chase_referrals")) {
-               inst->chase_referrals_unset = true;      /* use OpenLDAP defaults */
+               inst->pool_inst.chase_referrals_unset = true;    /* use OpenLDAP defaults */
        }
 
        /*
@@ -1504,7 +1516,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
         *      connection pool.
         */
        if (!cf_pair_find(conf, "pool")) {
-               if (!inst->config_server) {
+               if (!inst->pool_inst.config_server) {
                        cf_log_err_cs(conf, "Configuration item 'server' must have a value");
                        goto error;
                }
@@ -1517,7 +1529,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                goto error;
        }
 
-       if (inst->admin_sasl.mech) {
+       if (inst->pool_inst.admin_sasl.mech) {
                cf_log_err_cs(conf, "Configuration item 'sasl.mech' not supported.  "
                              "Linked libldap does not provide ldap_sasl_interactive_bind function");
                goto error;
@@ -1543,8 +1555,8 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
        /*
         *      Now iterate over all the 'server' config items
         */
-       for (i = 0; i < talloc_array_length(inst->config_server); i++) {
-               char const *value = inst->config_server[i];
+       for (i = 0; i < talloc_array_length(inst->pool_inst.config_server); i++) {
+               char const *value = inst->pool_inst.config_server[i];
                size_t j;
 
                /*
@@ -1625,7 +1637,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                                 */
                                if (ldap_url->lud_scheme) {
                                        if (strcmp(ldap_url->lud_scheme, "ldaps") == 0) {
-                                               if (inst->start_tls == true) {
+                                               if (inst->pool_inst.start_tls == true) {
                                                        cf_log_err_cs(conf, "ldaps:// scheme is not compatible "
                                                                      "with 'start_tls'");
                                                        goto ldap_url_error;
@@ -1641,7 +1653,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                                        /*
                                         *      URL port overrides configured port.
                                         */
-                                       ldap_url->lud_port = inst->port;
+                                       ldap_url->lud_port = inst->pool_inst.port;
 
                                        /*
                                         *      If there's no URL port, then set it to the default
@@ -1656,7 +1668,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                                        cf_log_err_cs(conf, "Failed recombining URL components");
                                        goto ldap_url_error;
                                }
-                               inst->server = talloc_asprintf_append(inst->server, "%s ", url);
+                               inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s ", url);
                                free(url);
                        }
 #  else
@@ -1678,11 +1690,11 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                         *      port, we use the hard-coded default.
                         */
                        if (set_port_maybe) {
-                               ldap_url->lud_port = inst->port;
+                               ldap_url->lud_port = inst->pool_inst.port;
                                if (!ldap_url->lud_port) ldap_url->lud_port = default_port;
                        }
 
-                       inst->server = talloc_asprintf_append(inst->server, "%s:%i ",
+                       inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s:%i ",
                                                              ldap_url->lud_host ? ldap_url->lud_host : "localhost",
                                                              ldap_url->lud_port);
 #  endif
@@ -1709,7 +1721,7 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                        int     port = 0;
                        size_t  len;
 
-                       port = inst->port;
+                       port = inst->pool_inst.port;
 
                        /*
                         *      We don't support URLs if the library didn't provide
@@ -1736,39 +1748,44 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                        }
                        if (port == 0) port = LDAP_PORT;
 
-                       inst->server = talloc_asprintf_append(inst->server, "ldap://%.*s:%i ", (int) len, value, port);
+                       inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "ldap://%.*s:%i ", (int) len, value, port);
 #else
                        /*
                         *      ldap_init takes port, which can be overridden by :port so
                         *      we don't need to do any parsing here.
                         */
-                       inst->server = talloc_asprintf_append(inst->server, "%s ", value);
+                       inst->pool_inst.server = talloc_asprintf_append(inst->pool_inst.server, "%s ", value);
 #endif
                }
        }
-       if (inst->server) inst->server[talloc_array_length(inst->server) - 2] = '\0';
 
-       DEBUG4("rlm_ldap (%s) - LDAP server string: %s", inst->name, inst->server);
+       /*
+        *      inst->pool_inst.server be unset if connection pool sharing is used.
+        */
+       if (inst->pool_inst.server) {
+               inst->pool_inst.server[talloc_array_length(inst->pool_inst.server) - 2] = '\0';
+               DEBUG4("rlm_ldap (%s) - LDAP server string: %s", inst->name, inst->pool_inst.server);
+       }
 
 #ifdef LDAP_OPT_X_TLS_NEVER
        /*
         *      Workaround for servers which support LDAPS but not START TLS
         */
-       if (inst->port == LDAPS_PORT || inst->tls_mode) {
-               inst->tls_mode = LDAP_OPT_X_TLS_HARD;
+       if (inst->pool_inst.port == LDAPS_PORT || inst->pool_inst.tls_mode) {
+               inst->pool_inst.tls_mode = LDAP_OPT_X_TLS_HARD;
        } else {
-               inst->tls_mode = 0;
+               inst->pool_inst.tls_mode = 0;
        }
 #endif
 
        /*
         *      Convert dereference strings to enumerated constants
         */
-       if (inst->dereference_str) {
-               inst->dereference = fr_str2int(ldap_dereference, inst->dereference_str, -1);
-               if (inst->dereference < 0) {
+       if (inst->pool_inst.dereference_str) {
+               inst->pool_inst.dereference = fr_str2int(ldap_dereference, inst->pool_inst.dereference_str, -1);
+               if (inst->pool_inst.dereference < 0) {
                        cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', "
-                                     "'finding' or 'always'", inst->dereference_str);
+                                     "'finding' or 'always'", inst->pool_inst.dereference_str);
                        goto error;
                }
        }
@@ -1856,15 +1873,16 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
        }
 #endif
 
-       if (inst->tls_require_cert_str) {
+       if (inst->pool_inst.tls_require_cert_str) {
 #ifdef LDAP_OPT_X_TLS_NEVER
                /*
                 *      Convert cert strictness to enumerated constants
                 */
-               inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1);
-               if (inst->tls_require_cert < 0) {
+               inst->pool_inst.tls_require_cert = fr_str2int(ldap_tls_require_cert,
+                                                             inst->pool_inst.tls_require_cert_str, -1);
+               if (inst->pool_inst.tls_require_cert < 0) {
                        cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', "
-                                     "'demand', 'allow', 'try' or 'hard'", inst->tls_require_cert_str);
+                                     "'demand', 'allow', 'try' or 'hard'", inst->pool_inst.tls_require_cert_str);
                        goto error;
                }
 #else
@@ -1886,11 +1904,6 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                return -1;
        }
 
-       /*
-        *      Initialise the directory mutex
-        */
-       pthread_mutex_init(&inst->directory_mutex, NULL);
-
        /*
         *      Set global options
         */
index a958d36038e521e9c0a38ded7f7f41aa63b75e6b..14092cbbd002ff7e089e08eafb2b71d3a2c50332 100644 (file)
@@ -133,7 +133,7 @@ typedef enum {
 
 extern FR_NAME_NUMBER const ldap_supported_extensions[];
 
-typedef struct ldap_instance rlm_ldap_t;
+typedef struct rlm_ldap_s rlm_ldap_t;
 
 typedef struct ldap_acct_section {
        CONF_SECTION    *cs;                            //!< Section configuration.
@@ -159,25 +159,6 @@ typedef struct rlm_ldap_control {
                                                        //!< we've finished using it.
 } rlm_ldap_control_t;
 
-/** Tracks the state of a libldap connection handle
- *
- */
-typedef struct ldap_handle {
-       LDAP            *handle;                        //!< libldap handle.
-       bool            rebound;                        //!< Whether the connection has been rebound to something
-                                                       //!< other than the admin user.
-       bool            referred;                       //!< Whether the connection is now established a server
-                                                       //!< other than the configured one.
-
-       rlm_ldap_control_t serverctrls[LDAP_MAX_CONTROLS + 1];  //!< Server controls to use for all operations with
-                                                               //!< this handle.
-       rlm_ldap_control_t clientctrls[LDAP_MAX_CONTROLS + 1];  //!< Client controls to use for all operations with
-                                                               //!< this handle.
-       int             serverctrls_cnt;                //!< Number of server controls associated with the handle.
-       int             clientctrls_cnt;                //!< Number of client controls associated with the handle.
-
-       rlm_ldap_t const *inst;                         //!< rlm_ldap configuration.
-} ldap_handle_t;
 
 typedef enum {
        LDAP_DIRECTORY_UNKNOWN = 0,                     //!< We can't determine the directory server.
@@ -206,14 +187,15 @@ typedef struct ldap_directory {
                                                        //!< password.
 } ldap_directory_t;
 
-struct ldap_instance {
-       char const      *name;                          //!< Instance name.
-
-       CONF_SECTION    *cs;                            //!< Main configuration section for this instance.
-       fr_connection_pool_t *pool;                     //!< Connection pool instance.
-
-       char const      **config_server;                //!< Server set in the config.
+/** Pool configuration
+ *
+ * Must not be passed into functions except via the connection handle
+ * this avoids problems with not using the connection pool configuration.
+ */
+typedef struct {
        char            *server;                        //!< Initial server to bind to.
+       char const      **config_server;                //!< Server set in the config.
+
        uint16_t        port;                           //!< Port to use when binding to the server.
 
        char const      *admin_identity;                //!< Identity we bind as when we need to query the LDAP
@@ -222,8 +204,8 @@ struct ldap_instance {
 
        ldap_sasl       admin_sasl;                     //!< SASL parameters used when binding as the admin.
 
-       char const      *dereference_str;               //!< When to dereference (never, searching, finding, always)
        int             dereference;                    //!< libldap value specifying dereferencing behaviour.
+       char const      *dereference_str;               //!< When to dereference (never, searching, finding, always)
 
        bool            chase_referrals;                //!< If the LDAP server returns a referral to another server
                                                        //!< or point in the tree, follow it, establishing new
@@ -238,10 +220,65 @@ struct ldap_instance {
                                                        //!< referrals on the same server, but won't bind to other
                                                        //!< servers.
 
-       uint32_t        ldap_debug;                     //!< Debug flag for the SDK.
+       /*
+        *      TLS items.
+        */
+       int             tls_mode;
+       bool            start_tls;                      //!< Send the Start TLS message to the LDAP directory
+                                                       //!< to start encrypted communications using the standard
+                                                       //!< LDAP port.
+
+       char const      *tls_ca_file;                   //!< Sets the full path to a CA certificate (used to validate
+                                                       //!< the certificate the server presents).
 
-       ldap_directory_t *directory;                    //!< Server capabilities.
-       pthread_mutex_t directory_mutex;                //!< Sync modifications to directory structure.
+       char const      *tls_ca_path;                   //!< Sets the path to a directory containing CA certificates.
+
+       char const      *tls_certificate_file;          //!< Sets the path to the public certificate file we present
+                                                       //!< to the servers.
+
+       char const      *tls_private_key_file;          //!< Sets the path to the private key for our public
+                                                       //!< certificate.
+
+       char const      *tls_require_cert_str;          //!< Sets requirements for validating the certificate the
+                                                       //!< server presents.
+
+       int             tls_require_cert;               //!< OpenLDAP constant representing the require cert string.
+
+       /*
+        *      Options
+        */
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+       bool            session_tracking;               //!< Whether we add session tracking controls, which help
+                                                       //!< identify the autz or acct session the commands were
+                                                       //!< issued for.
+#endif
+
+       /*
+        *      For keep-alives.
+        */
+#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
+       uint32_t        keepalive_idle;                 //!< Number of seconds a connections needs to remain idle
+                                                       //!< before TCP starts sending keepalive probes.
+#endif
+#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
+       uint32_t        keepalive_probes;               //!< Number of missed timeouts before the connection is
+                                                       //!< dropped.
+#endif
+#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
+       uint32_t        keepalive_interval;             //!< Interval between keepalive probes.
+#endif
+
+       /*
+        *      Search timelimits
+        */
+       uint32_t        srv_timelimit;                  //!< How long the server should spent on a single request
+                                                       //!< (also bounded by value on the server).
+} ldap_pool_inst_t;
+
+struct rlm_ldap_s {
+       char const      *name;                          //!< Instance name.
+
+       CONF_SECTION    *cs;                            //!< Main configuration section for this instance.
 
        bool            expect_password;                //!< True if the user_map included a mapping between an LDAP
                                                        //!< attribute and one of our password reference attributes.
@@ -251,6 +288,11 @@ struct ldap_instance {
         */
        vp_map_t        *user_map;                      //!< Attribute map applied to users and profiles.
 
+       /*
+        *      Search time limits
+        */
+       uint32_t        res_timeout;                    //!< How long we wait for a result from the server.
+
        /*
         *      User object attributes and filters
         */
@@ -267,10 +309,11 @@ struct ldap_instance {
        bool            access_positive;                //!< If true the presence of the attribute will allow access,
                                                        //!< else it will deny access.
 
+       ldap_sasl_dynamic user_sasl;                    //!< SASL parameters used when binding as the user.
+
        char const      *valuepair_attr;                //!< Generic dynamic mapping attribute, contains a RADIUS
                                                        //!< attribute and value.
 
-       ldap_sasl_dynamic user_sasl;                    //!< SASL parameters used when binding as the user.
 
        /*
         *      Group object attributes and filters
@@ -333,46 +376,6 @@ struct ldap_instance {
        ldap_acct_section_t *postauth;                  //!< Modify mappings for post-auth.
        ldap_acct_section_t *accounting;                //!< Modify mappings for accounting.
 
-       /*
-        *      TLS items.  We should really normalize these with the
-        *      TLS code in 3.0.
-        */
-       int             tls_mode;
-       bool            start_tls;                      //!< Send the Start TLS message to the LDAP directory
-                                                       //!< to start encrypted communications using the standard
-                                                       //!< LDAP port.
-
-       char const      *tls_ca_file;                   //!< Sets the full path to a CA certificate (used to validate
-                                                       //!< the certificate the server presents).
-
-       char const      *tls_ca_path;                   //!< Sets the path to a directory containing CA certificates.
-
-       char const      *tls_certificate_file;          //!< Sets the path to the public certificate file we present
-                                                       //!< to the servers.
-
-       char const      *tls_private_key_file;          //!< Sets the path to the private key for our public
-                                                       //!< certificate.
-
-       char const      *tls_random_file;               //!< Path to the random file if /dev/random and /dev/urandom
-                                                       //!< are unavailable.
-
-       char const      *tls_require_cert_str;          //!< Sets requirements for validating the certificate the
-                                                       //!< server presents.
-
-       int             tls_require_cert;               //!< OpenLDAP constant representing the require cert string.
-
-       /*
-        *      Options
-        */
-#ifdef LDAP_CONTROL_X_SESSION_TRACKING
-       bool            session_tracking;               //!< Whether we add session tracking controls, which help
-                                                       //!< identify the autz or acct session the commands were
-                                                       //!< issued for.
-#endif
-       uint32_t        res_timeout;                    //!< How long we wait for a result from the server.
-       uint32_t        srv_timelimit;                  //!< How long the server should spent on a single request
-                                                       //!< (also bounded by value on the server).
-
 #ifdef WITH_EDIR
        /*
         *      eDir support
@@ -382,22 +385,42 @@ struct ldap_instance {
        bool            edir_autz;                      //!< If true, and we have the Universal Password, bind with it
                                                        //!< to perform additional authorisation checks.
 #endif
+
+       fr_connection_pool_t *pool;                     //!< Connection pool instance.
+       ldap_pool_inst_t pool_inst;                     //!< Connection configuration instance.
+
        /*
-        *      For keep-alives.
+        *      Global config
         */
-#ifdef LDAP_OPT_X_KEEPALIVE_IDLE
-       uint32_t        keepalive_idle;                 //!< Number of seconds a connections needs to remain idle
-                                                       //!< before TCP starts sending keepalive probes.
-#endif
-#ifdef LDAP_OPT_X_KEEPALIVE_PROBES
-       uint32_t        keepalive_probes;               //!< Number of missed timeouts before the connection is
-                                                       //!< dropped.
-#endif
-#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL
-       uint32_t        keepalive_interval;             //!< Interval between keepalive probes.
-#endif
+       char const      *tls_random_file;               //!< Path to the random file if /dev/random and /dev/urandom
+                                                       //!< are unavailable.
+
+       uint32_t        ldap_debug;                     //!< Debug flag for the SDK.
 };
 
+/** Tracks the state of a libldap connection handle
+ *
+ */
+typedef struct ldap_handle {
+       LDAP            *handle;                        //!< libldap handle.
+       bool            rebound;                        //!< Whether the connection has been rebound to something
+                                                       //!< other than the admin user.
+       bool            referred;                       //!< Whether the connection is now established a server
+                                                       //!< other than the configured one.
+
+       rlm_ldap_control_t serverctrls[LDAP_MAX_CONTROLS + 1];  //!< Server controls to use for all operations with
+                                                               //!< this handle.
+       rlm_ldap_control_t clientctrls[LDAP_MAX_CONTROLS + 1];  //!< Client controls to use for all operations with
+                                                               //!< this handle.
+       int             serverctrls_cnt;                //!< Number of server controls associated with the handle.
+       int             clientctrls_cnt;                //!< Number of client controls associated with the handle.
+
+       ldap_directory_t *directory;                    //!< The type of directory we're connected to.
+
+       ldap_pool_inst_t const *pool_inst;              //!< rlm_ldap connection configuration.
+       rlm_ldap_t       const *inst;                   //!< rlm_ldap pool inst.
+} ldap_handle_t;
+
 /** Result of expanding the RHS of a set of maps
  *
  * Used to store the array of attributes we'll be querying for.
@@ -489,7 +512,7 @@ char const *rlm_ldap_find_user(rlm_ldap_t const *inst, REQUEST *request, ldap_ha
 rlm_rcode_t rlm_ldap_check_access(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn,
                                  LDAPMessage *entry);
 
-void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request);
+void rlm_ldap_check_reply(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t const *conn);
 
 /*
  *     ldap.c - Callbacks for the connection pool API.
@@ -563,7 +586,7 @@ int rlm_ldap_control_add_session_tracking(ldap_handle_t *conn, REQUEST *request)
 /*
  *     directory.c - Get directory capabilities from the remote server
  */
-int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t *inst, ldap_handle_t **pconn);
+int rlm_ldap_directory_alloc(TALLOC_CTX *ctx, ldap_directory_t **out, rlm_ldap_t const *inst, ldap_handle_t **pconn);
 
 /*
  *     edir.c - Magic extensions for Novell