]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add "ping" xlat for winbind, so we can run periodic checks against AD
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 16 Apr 2025 19:51:35 +0000 (14:51 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 16 Apr 2025 20:27:55 +0000 (15:27 -0500)
src/modules/rlm_winbind/rlm_winbind.c
src/tests/modules/winbind/ping.unlang [new file with mode: 0644]

index 4c323e8f3ae399cd5793b00c62ffb6417409969e..434f3966da0a275399993318efb1e001d0ea1ccd 100644 (file)
@@ -31,6 +31,9 @@ RCSID("$Id$")
 #include <freeradius-devel/unlang/call_env.h>
 #include <freeradius-devel/unlang/xlat_func.h>
 #include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/unlang/xlat.h>
+#include <freeradius-devel/util/dcursor.h>
+#include <freeradius-devel/util/value.h>
 
 #include "rlm_winbind.h"
 #include "auth_wbclient_pap.h"
@@ -238,6 +241,10 @@ error:
        return rcode;
 }
 
+static xlat_arg_parser_t const winbind_group_xlat_arg[] = {
+       { .required = true, .type = FR_TYPE_STRING, .concat = true },
+       XLAT_ARG_PARSER_TERMINATOR
+};
 
 /** Check if the user is a member of a particular winbind group
  *
@@ -267,6 +274,71 @@ static xlat_action_t winbind_group_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
        return XLAT_ACTION_DONE;
 }
 
+static xlat_arg_parser_t const winbind_ping_xlat_arg[] = {
+       { .required = false, .type = FR_TYPE_STRING },
+       XLAT_ARG_PARSER_TERMINATOR
+};
+
+
+/** Ping a specific domain
+ *
+ * Sends a noop style message to AD to check if winbind and AD are responsive.
+@verbatim
+%winbind.ping([<domain>])
+@endverbatim
+ */
+static xlat_action_t winbind_ping_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
+                                      xlat_ctx_t const *xctx,
+                                      request_t *request, fr_value_box_list_t *in)
+{
+       rlm_winbind_thread_t    *t = talloc_get_type_abort(xctx->mctx->thread, rlm_winbind_thread_t);
+       fr_value_box_t const    *domain = fr_value_box_list_head(in);
+       winbind_ctx_t           *wbctx;
+       char                    *dc = NULL;
+       struct wbcAuthErrorInfo *err_info = NULL;
+       wbcErr                  err;
+       fr_value_box_t          *out_vb;
+       fr_time_t               then, now;
+
+       wbctx = winbind_slab_reserve(t->slab);
+       if (!wbctx) {
+               RERROR("Ping failed - Unable to get winbind context");
+               return XLAT_ACTION_FAIL;
+       }
+
+       then = fr_time();
+       /*
+        *      Yes, this is a synchronous call, no, we can't set an explicit timeout
+        */
+       err = wbcCtxPingDc2(wbctx->ctx, domain ? domain->vb_strvalue : NULL, &err_info, &dc);
+       now = fr_time();
+
+       MEM(out_vb = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL));
+       if (WBC_ERROR_IS_OK(err)) {
+               RDEBUG2("Ping succeeded to DC %s after %pVms", dc,
+                       fr_box_time_delta_msec(fr_time_sub(now, then)));
+
+               MEM(out_vb = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL));
+               MEM(fr_value_box_strdup(out_vb, out_vb, NULL, "ok", false) == 0);
+       } else {
+               char const *err_str = wbcErrorString(err);
+
+               RERROR("Ping failed (%s) to DC %s after %pVms%s%s", err_str, dc,
+                      fr_box_time_delta_msec(fr_time_sub(now, then)),
+                      err_info->display_string ? " - " : "",
+                      err_info->display_string ? err_info->display_string : "");
+
+               MEM(fr_value_box_strdup(out_vb, out_vb, NULL, err_str, false) == 0);
+       }
+
+       if (dc) wbcFreeMemory(dc);
+       if (err_info) wbcFreeMemory(err_info);
+       winbind_slab_release(wbctx);
+
+       fr_dcursor_append(out, out_vb);
+
+       return XLAT_ACTION_DONE;
+}
 
 /*
  *     Free winbind context
@@ -291,12 +363,6 @@ static int winbind_ctx_alloc(winbind_ctx_t *wbctx, UNUSED void *uctx)
        return 0;
 }
 
-static xlat_arg_parser_t const winbind_group_xlat_arg[] = {
-       { .required = true, .type = FR_TYPE_STRING, .concat = true },
-       XLAT_ARG_PARSER_TERMINATOR
-};
-
-
 /** Instantiate this module
  *
  * @param[in] mctx     data for this module
@@ -521,6 +587,13 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx)
        xlat_func_args_set(xlat, winbind_group_xlat_arg);
        xlat_func_call_env_set(xlat, &winbind_group_xlat_call_env);
 
+       xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, "ping", winbind_ping_xlat, FR_TYPE_STRING);
+       if (!xlat) {
+               cf_log_err(conf, "Failed registering ping expansion");
+               return -1;
+       }
+       xlat_func_args_set(xlat, winbind_ping_xlat_arg);
+
        return 0;
 }
 
diff --git a/src/tests/modules/winbind/ping.unlang b/src/tests/modules/winbind/ping.unlang
new file mode 100644 (file)
index 0000000..6a123b6
--- /dev/null
@@ -0,0 +1,5 @@
+if (%winbind.ping() != 'ok') {
+       test_fail
+}
+
+test_pass