]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Switch rlm_winbind from fr_pool_t to slab allocation for connection ctx
authorNick Porter <nick@portercomputing.co.uk>
Thu, 5 Dec 2024 11:33:24 +0000 (11:33 +0000)
committerNick Porter <nick@portercomputing.co.uk>
Thu, 5 Dec 2024 11:33:24 +0000 (11:33 +0000)
src/modules/rlm_winbind/auth_wbclient_pap.c
src/modules/rlm_winbind/auth_wbclient_pap.h
src/modules/rlm_winbind/rlm_winbind.c
src/modules/rlm_winbind/rlm_winbind.h

index cb91a2ea9766e04cf8a3acb1a2aa31b84f8fbf41..e96159eed400fd673d567d91ac68bcff27c84a7b 100644 (file)
@@ -37,9 +37,9 @@ RCSID("$Id$")
 
 /** PAP authentication direct to winbind via Samba's libwbclient library
  *
- * @param[in] inst Module instance
  * @param[in] request The current request
  * @param[in] env The call_env for the current winbind authentication
+ * @param[in] t The module thread instance data.
  *
  * @return
  *     - 0     Success
@@ -47,9 +47,10 @@ RCSID("$Id$")
  *     - -648  Password expired
  *
  */
-int do_auth_wbclient_pap(rlm_winbind_t const *inst, request_t *request, winbind_auth_call_env_t *env)
+int do_auth_wbclient_pap(request_t *request, winbind_auth_call_env_t *env, rlm_winbind_thread_t *t)
 {
        int                             ret = -1;
+       winbind_ctx_t                   *wbctx;
        struct wbcContext               *wb_ctx;
        struct wbcAuthUserParams        authparams;
        wbcErr                          err;
@@ -94,19 +95,19 @@ int do_auth_wbclient_pap(rlm_winbind_t const *inst, request_t *request, winbind_
        /*
         * Send auth request across to winbind
         */
-       wb_ctx = fr_pool_connection_get(inst->wb_pool, request);
-       if (wb_ctx == NULL) {
-               RERROR("Unable to get winbind connection from pool");
+       wbctx = winbind_slab_reserve(t->slab);
+       if (!wbctx) {
+               RERROR("Unable to get winbind context");
                goto done;
        }
+       wb_ctx = wbctx->ctx;
 
        RDEBUG2("Sending authentication request user='%s' domain='%s'", authparams.account_name,
                                                                        authparams.domain_name);
 
        err = wbcCtxAuthenticateUserEx(wb_ctx, &authparams, &info, &error);
 
-       fr_pool_connection_release(inst->wb_pool, request, wb_ctx);
-
+       winbind_slab_release(wbctx);
 
        /*
         * Try and give some useful feedback on what happened. There are only
index b749b7f53b6d5071d7638f3efd7ec3bc6a42e4d2..bf97fb9442cdb1144b6016de2d8180190bb2c8af 100644 (file)
@@ -4,4 +4,4 @@
 
 RCSIDH(auth_wbclient_h, "$Id$")
 
-int do_auth_wbclient_pap(rlm_winbind_t const *inst, request_t *request, winbind_auth_call_env_t *env);
+int do_auth_wbclient_pap(request_t *request, winbind_auth_call_env_t *env, rlm_winbind_thread_t *t);
index 95d0fc72d8239a9a221c94699b25fb9503152dc2..90ab216eca66fb57b6787fa8a6a6d66855472976 100644 (file)
@@ -42,8 +42,16 @@ static const conf_parser_t group_config[] = {
        CONF_PARSER_TERMINATOR
 };
 
+static conf_parser_t reuse_winbind_config[] = {
+       { FR_CONF_OFFSET("min", fr_slab_config_t, min_elements), .dflt = "10" },
+       { FR_CONF_OFFSET("max", fr_slab_config_t, max_elements), .dflt = "100" },
+       { FR_CONF_OFFSET("cleanup_interval", fr_slab_config_t, interval), .dflt = "30s" },
+       CONF_PARSER_TERMINATOR
+};
+
 static const conf_parser_t module_config[] = {
        { FR_CONF_POINTER("group", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) group_config },
+       { FR_CONF_OFFSET_SUBSECTION("reuse", 0, rlm_winbind_t, reuse, reuse_winbind_config) },
        CONF_PARSER_TERMINATOR
 };
 
@@ -86,9 +94,10 @@ typedef struct {
  *     - 1 failure or user is not in group
  */
 static bool winbind_check_group(rlm_winbind_t const *inst, request_t *request, char const *name,
-                               winbind_group_xlat_call_env_t *env)
+                               winbind_group_xlat_call_env_t *env, rlm_winbind_thread_t *t)
 {
        bool                    rcode = false;
+       winbind_ctx_t           *wbctx;
        struct wbcContext       *wb_ctx;
        wbcErr                  err;
        uint32_t                num_groups, i;
@@ -125,13 +134,14 @@ static bool winbind_check_group(rlm_winbind_t const *inst, request_t *request, c
        }
 
        /*
-        *      Get a libwbclient connection from the pool
+        *      Get a libwbclient context
         */
-       wb_ctx = fr_pool_connection_get(inst->wb_pool, request);
-       if (wb_ctx == NULL) {
-               RERROR("Unable to get winbind connection from the pool");
+       wbctx = winbind_slab_reserve(t->slab);
+       if (!wbctx) {
+               RERROR("Unable to get winbind context");
                goto error;
        }
+       wb_ctx = wbctx->ctx;
 
        RDEBUG2("Trying to find user \"%s\" in group \"%s\"", username, name);
 
@@ -221,7 +231,7 @@ static bool winbind_check_group(rlm_winbind_t const *inst, request_t *request, c
 
 finish:
        wbcFreeMemory(wb_groups);
-       fr_pool_connection_release(inst->wb_pool, request, wb_ctx);
+       winbind_slab_release(wbctx);
 
 error:
        talloc_free(username_buff);
@@ -245,6 +255,7 @@ static xlat_action_t winbind_group_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
 {
        rlm_winbind_t const     *inst = talloc_get_type_abort(xctx->mctx->mi->data, rlm_winbind_t);
        winbind_group_xlat_call_env_t   *env = talloc_get_type_abort(xctx->env_data, winbind_group_xlat_call_env_t);
+       rlm_winbind_thread_t    *t = talloc_get_type_abort(xctx->mctx->thread, rlm_winbind_thread_t);
        fr_value_box_t          *arg = fr_value_box_list_head(in);
        char const              *p = arg->vb_strvalue;
        fr_value_box_t          *vb;
@@ -252,53 +263,36 @@ static xlat_action_t winbind_group_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
        fr_skip_whitespace(p);
 
        MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, attr_expr_bool_enum));
-       vb->vb_bool = winbind_check_group(inst, request, p, env);
+       vb->vb_bool = winbind_check_group(inst, request, p, env, t);
        fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
 
 
-/** Free connection pool winbind context
- *
- * @param[in] wb_ctx libwbclient context
- * @return 0
+/*
+ *     Free winbind context
  */
-static int _mod_conn_free(struct wbcContext **wb_ctx)
+static int _mod_ctx_free(winbind_ctx_t *wbctx)
 {
-       wbcCtxFree(*wb_ctx);
-
+       wbcCtxFree(wbctx->ctx);
        return 0;
 }
 
-
-/** Create connection pool winbind context
- *
- * @param[in] ctx      talloc context
- * @param[in] instance Module instance (unused)
- * @param[in] timeout  Connection timeout
- *
- * @return pointer to libwbclient context
+/*
+ *     Create winbind context
  */
-static void *mod_conn_create(TALLOC_CTX *ctx, UNUSED void *instance, UNUSED fr_time_delta_t timeout)
+static int winbind_ctx_alloc(winbind_ctx_t *wbctx, UNUSED void *uctx)
 {
-       struct wbcContext **wb_ctx;
-
-       wb_ctx = talloc_zero(ctx, struct wbcContext *);
-       *wb_ctx = wbcCtxCreate();
-
-       if (*wb_ctx == NULL) {
-               PERROR("failed to create winbind context");
-               talloc_free(wb_ctx);
-               return NULL;
+       wbctx->ctx = wbcCtxCreate();
+       if (!wbctx->ctx) {
+               fr_strerror_printf("Unable to create winbind context");
+               return -1;
        }
-
-       talloc_set_destructor(wb_ctx, _mod_conn_free);
-
-       return *wb_ctx;
+       talloc_set_destructor(wbctx, _mod_ctx_free);
+       return 0;
 }
 
-
 static xlat_arg_parser_t const winbind_group_xlat_arg[] = {
        { .required = true, .type = FR_TYPE_STRING, .concat = true },
        XLAT_ARG_PARSER_TERMINATOR
@@ -316,13 +310,6 @@ static xlat_arg_parser_t const winbind_group_xlat_arg[] = {
 static int mod_instantiate(module_inst_ctx_t const *mctx)
 {
        rlm_winbind_t                   *inst = talloc_get_type_abort(mctx->mi->data, rlm_winbind_t);
-       CONF_SECTION                    *conf = mctx->mi->conf;
-
-       inst->wb_pool = module_rlm_connection_pool_init(conf, inst, mod_conn_create, NULL, NULL, NULL, NULL);
-       if (!inst->wb_pool) {
-               cf_log_err(conf, "Unable to initialise winbind connection pool");
-               return -1;
-       }
 
        inst->auth_type = fr_dict_enum_by_name(attr_auth_type, mctx->mi->name, -1);
        if (!inst->auth_type) {
@@ -334,23 +321,6 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
 }
 
 
-/** Tidy up module instance
- *
- * Frees up the libwbclient connection pool.
- *
- * @param[in] mctx     data for this module
- * @return 0
- */
-static int mod_detach(module_detach_ctx_t const *mctx)
-{
-       rlm_winbind_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_winbind_t);
-
-       fr_pool_free(inst->wb_pool);
-
-       return 0;
-}
-
-
 /** Authorize for libwbclient/winbind authentication
  *
  * Checks there is a password available so we can authenticate
@@ -395,8 +365,8 @@ static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, mod
  */
 static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
 {
-       rlm_winbind_t const     *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_winbind_t);
        winbind_auth_call_env_t *env = talloc_get_type_abort(mctx->env_data, winbind_auth_call_env_t);
+       rlm_winbind_thread_t    *t = talloc_get_type_abort(mctx->thread, rlm_winbind_thread_t);
 
        /*
         *      Make sure the supplied password isn't empty
@@ -420,7 +390,7 @@ static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result,
         *      many debug outputs or errors as the auth function is
         *      chatty enough.
         */
-       if (do_auth_wbclient_pap(inst, request, env) == 0) {
+       if (do_auth_wbclient_pap(request, env, t) == 0) {
                RDEBUG2("User authenticated successfully using winbind");
                RETURN_MODULE_OK;
        }
@@ -556,6 +526,27 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx)
        return 0;
 }
 
+static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
+{
+       rlm_winbind_t const     *inst = talloc_get_type_abort(mctx->mi->data, rlm_winbind_t);
+       rlm_winbind_thread_t    *t = talloc_get_type_abort(mctx->thread, rlm_winbind_thread_t);
+
+       t->inst = inst;
+       if (!(t->slab = winbind_slab_list_alloc(t, mctx->el, &inst->reuse, winbind_ctx_alloc, NULL, NULL, false, false))) {
+               ERROR("Connection handle pool instantiation failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
+{
+       rlm_winbind_thread_t    *t = talloc_get_type_abort(mctx->thread, rlm_winbind_thread_t);
+       talloc_free(t->slab);
+       return 0;
+}
+
 /*
  *     The module name should be the only globally exported symbol.
  *     That is, everything else should be 'static'.
@@ -574,7 +565,9 @@ module_rlm_t rlm_winbind = {
                .config         = module_config,
                .instantiate    = mod_instantiate,
                .bootstrap      = mod_bootstrap,
-               .detach         = mod_detach
+               .thread_inst_size       = sizeof(rlm_winbind_thread_t),
+               .thread_instantiate     = mod_thread_instantiate,
+               .thread_detach          = mod_thread_detach,
        },
        .method_group = {
                .bindings = (module_method_binding_t[]){
index e20041a558a50ac23179e375f5dea328a58a042e..473cca3fdf77403cebc3236708b965047e680164 100644 (file)
@@ -3,19 +3,31 @@
 
 #include "config.h"
 #include <wbclient.h>
-#include <freeradius-devel/server/pool.h>
+#include <freeradius-devel/util/slab.h>
 
 /*
  *      Structure for the module configuration.
  */
 typedef struct {
-       fr_pool_t               *wb_pool;
-       fr_dict_enum_value_t            *auth_type;
+       fr_dict_enum_value_t    *auth_type;
 
        /* group config */
        bool                    group_add_domain;
+       fr_slab_config_t        reuse;
 } rlm_winbind_t;
 
+typedef struct {
+       struct wbcContext       *ctx;
+} winbind_ctx_t;
+
+FR_SLAB_TYPES(winbind, winbind_ctx_t)
+FR_SLAB_FUNCS(winbind, winbind_ctx_t)
+
+typedef struct {
+       rlm_winbind_t const     *inst;          //!< Instance of rlm_winbind
+       winbind_slab_list_t     *slab;          //!< Slab list for winbind handles.
+} rlm_winbind_thread_t;
+
 typedef struct {
        fr_value_box_t  username;
        fr_value_box_t  domain;