]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
winbind:varlink: Avoid recursion
authorSamuel Cabrero <scabrero@samba.org>
Wed, 17 Apr 2024 09:58:24 +0000 (11:58 +0200)
committerAndreas Schneider <asn@cryptomilk.org>
Thu, 20 Feb 2025 08:07:32 +0000 (08:07 +0000)
Avoid recursion while dispatching a call. This is similar to the _NO_WINBINDD
environment variable that nss_winbind uses, but on the server side.

Signed-off-by: Samuel Cabrero <scabrero@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/winbindd/winbindd_varlink.c
source3/winbindd/winbindd_varlink.h
source3/winbindd/winbindd_varlink_getgrouprecord.c
source3/winbindd/winbindd_varlink_getmemberships.c
source3/winbindd/winbindd_varlink_getuserrecord.c

index 857ea5f14d60d241f805c4e6ab79bc4299a48907..02ef7c32478b6d213f380cdcf5cd7a048e411ed1 100644 (file)
@@ -51,6 +51,8 @@ static const char s_interface[] =
 "error ConflictingRecordFound ()\n"
 "error EnumerationNotSupported ()\n";
 
+bool vl_active = false;
+
 struct wb_vl_state {
        VarlinkService *service;
        struct tevent_context *ev_ctx;
@@ -164,10 +166,19 @@ static long io_systemd_getuserrecord(VarlinkService *service,
        }
 
        DBG_DEBUG("GetUserRecord call parameters: service='%s', "
-                 "userName='%s', uid='%" PRId64 "'\n",
+                 "userName='%s', uid='%" PRId64 ", vl_active=%s'\n",
                  parm_service,
                  parm_name,
-                 parm_uid);
+                 parm_uid,
+                 vl_active ? "1" : "0");
+
+       if (vl_active) {
+               DBG_DEBUG("Varlink service dispatching call, avoid recursion\n");
+               goto fail;
+       }
+
+       /* Flag will be unset by state talloc destructors */
+       vl_active = true;
 
        /*
         * The wb_vl_user_* functions will reply theirselves when return
@@ -216,6 +227,7 @@ fail:
        varlink_call_reply_error(call,
                                 WB_VL_REPLY_ERROR_SERVICE_NOT_AVAILABLE,
                                 NULL);
+       vl_active = false;
        return 0;
 }
 
@@ -273,11 +285,19 @@ static long io_systemd_getgrouprecord(VarlinkService *service,
        }
 
        DBG_DEBUG("GetGroupRecord call parameters: service='%s', "
-                 "groupName='%s', gid='%" PRId64 "'\n",
+                 "groupName='%s', gid='%" PRId64 "', vl_active=%s\n",
                  parm_service,
                  parm_name,
-                 parm_gid);
+                 parm_gid,
+                 vl_active ? "1" : "0");
+
+       if (vl_active) {
+               DBG_DEBUG("Varlink service dispatching call, avoid recursion\n");
+               goto fail;
+       }
 
+       /* Flag will be unset by state talloc destructors */
+       vl_active = true;
        /*
         * The wb_vl_group_* functions will reply theirselves when return
         * NT_STATUS_OK
@@ -325,6 +345,7 @@ fail:
        varlink_call_reply_error(call,
                                 WB_VL_REPLY_ERROR_SERVICE_NOT_AVAILABLE,
                                 NULL);
+       vl_active = false;
        return 0;
 }
 
@@ -384,10 +405,19 @@ static long io_systemd_getmemberships(VarlinkService *service,
        }
 
        DBG_DEBUG("GetMemberships call parameters: service='%s', "
-                 "userName='%s', groupName='%s'\n",
+                 "userName='%s', groupName='%s', vl_active=%s\n",
                  parm_service,
                  parm_username,
-                 parm_groupname);
+                 parm_groupname,
+                 vl_active ? "1" : "0");
+
+       if (vl_active) {
+               DBG_DEBUG("Varlink service dispatching call, avoid recursion\n");
+               goto fail;
+       }
+
+       /* Flag will be unset by state talloc destructors */
+       vl_active = true;
 
        /*
         * The wb_vl_membership_* functions will reply theirselves when return
@@ -436,6 +466,7 @@ fail:
        varlink_call_reply_error(call,
                                 WB_VL_REPLY_ERROR_SERVICE_NOT_AVAILABLE,
                                 NULL);
+       vl_active = false;
        return 0;
 }
 
index 0508bc689ff7773d76a7ccd93f2f25fff3aa332b..ae30928f8b2fecaf637db9f631c9b26b7919312b 100644 (file)
@@ -24,6 +24,8 @@
 #include <tevent.h>
 #include <varlink.h>
 
+extern bool vl_active;
+
 #define WB_VL_SERVICE_NAME "org.samba.winbind"
 
 #define WB_VL_REPLY_ERROR_NO_RECORD_FOUND \
index abb98ece5d1008185072e0e061246ee69811dc0c..63e2ddd435800c75040dad8353abf7e3e7155756 100644 (file)
@@ -86,6 +86,8 @@ static int group_enum_state_destructor(struct group_enum_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -326,27 +328,30 @@ NTSTATUS wb_vl_group_enumerate(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct group_enum_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = false;
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_set_destructor(s, group_enum_state_destructor);
+
        /* Check if enumeration enabled */
        if (!lp_winbind_enum_groups()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Enum request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct group_enum_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, group_enum_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
@@ -408,6 +413,8 @@ static int group_by_gid_state_destructor(struct group_by_gid_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -475,6 +482,7 @@ NTSTATUS wb_vl_group_by_gid(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct group_by_gid_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = false;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, group_by_gid_state_destructor);
@@ -541,6 +549,8 @@ static int group_by_name_state_destructor(struct group_by_name_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -609,6 +619,7 @@ NTSTATUS wb_vl_group_by_name(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct group_by_name_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = false;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, group_by_name_state_destructor);
@@ -679,6 +690,8 @@ static int group_by_name_gid_state_destructor(struct group_by_name_gid_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -797,6 +810,7 @@ NTSTATUS wb_vl_group_by_name_and_gid(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct group_by_name_gid_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = false;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, group_by_name_gid_state_destructor);
index cc14062463ee6003747d1d650df54ee6f1c261ed..780e99f4f2acaa8f6319b5ee18a3d2ee5aa39d3b 100644 (file)
@@ -78,6 +78,8 @@ static int membership_enum_state_destructor(struct membership_enum_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -349,13 +351,22 @@ NTSTATUS wb_vl_memberships_enumerate(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct membership_enum_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = false;
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       talloc_set_destructor(s, membership_enum_state_destructor);
        /* Check if enumeration enabled */
        if (!lp_winbind_enum_groups()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check if group expansion is enabled */
@@ -364,21 +375,16 @@ NTSTATUS wb_vl_memberships_enumerate(TALLOC_CTX *mem_ctx,
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Enum request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct membership_enum_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, membership_enum_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
@@ -446,6 +452,8 @@ memberships_by_user_state_destructor(struct memberships_by_user_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -597,27 +605,30 @@ NTSTATUS wb_vl_memberships_by_user(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct memberships_by_user_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = false;
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_set_destructor(s, memberships_by_user_state_destructor);
+
        /* Check if group expansion is enabled */
        if (!lp_winbind_expand_groups()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct memberships_by_user_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, memberships_by_user_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
@@ -690,6 +701,8 @@ memberships_by_group_state_destructor(struct memberships_by_group_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -765,27 +778,30 @@ NTSTATUS wb_vl_memberships_by_group(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct memberships_by_group_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = false;
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_set_destructor(s, memberships_by_group_state_destructor);
+
        /* Check if group expansion is enabled */
        if (!lp_winbind_expand_groups()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct memberships_by_group_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, memberships_by_group_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
@@ -859,6 +875,8 @@ static int membership_check_state_destructor(struct membership_check_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -952,27 +970,30 @@ NTSTATUS wb_vl_membership_check(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct membership_check_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = false;
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_set_destructor(s, membership_check_state_destructor);
+
        /* Check if group expansion is enabled */
        if (!lp_winbind_expand_groups()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct membership_check_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, membership_check_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
index bc6f7781eb7510948f7de7ac6905cff9997b153a..d96d8f47fb5c3a212b164f25ddd34b6a35448f31 100644 (file)
@@ -76,6 +76,8 @@ static int user_enum_state_destructor(struct user_enum_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = 0;
+
        return 0;
 }
 
@@ -300,27 +302,30 @@ NTSTATUS wb_vl_user_enumerate(TALLOC_CTX *mem_ctx,
        struct tevent_req *req = NULL;
        NTSTATUS status;
 
+       s = talloc_zero(mem_ctx, struct user_enum_state);
+       if (s == NULL) {
+               DBG_ERR("No memory\n");
+               vl_active = 0;
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_set_destructor(s, user_enum_state_destructor);
+
        /* Check if enumeration enabled */
        if (!lp_winbind_enum_users()) {
                varlink_call_reply_error(
                        call,
                        WB_VL_REPLY_ERROR_ENUMERATION_NOT_SUPPORTED,
                        NULL);
-               return NT_STATUS_OK;
+               status = NT_STATUS_OK;
+               goto fail;
        }
 
        /* Check more flag is set */
        if (!(flags & VARLINK_CALL_MORE)) {
                DBG_WARNING("Enum request without more flag set\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       s = talloc_zero(mem_ctx, struct user_enum_state);
-       if (s == NULL) {
-               DBG_ERR("No memory\n");
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto fail;
        }
-       talloc_set_destructor(s, user_enum_state_destructor);
 
        s->fake_cli = talloc_zero(s, struct winbindd_cli_state);
        if (s->fake_cli == NULL) {
@@ -382,6 +387,8 @@ static int user_by_uid_state_destructor(struct user_by_uid_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = 0;
+
        return 0;
 }
 
@@ -447,6 +454,7 @@ NTSTATUS wb_vl_user_by_uid(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct user_by_uid_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = 0;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, user_by_uid_state_destructor);
@@ -513,6 +521,8 @@ static int user_by_name_state_destructor(struct user_by_name_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = 0;
+
        return 0;
 }
 
@@ -577,6 +587,7 @@ NTSTATUS wb_vl_user_by_name(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct user_by_name_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = 0;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, user_by_name_state_destructor);
@@ -647,6 +658,8 @@ static int user_by_name_uid_state_destructor(struct user_by_name_uid_state *s)
                s->call = varlink_call_unref(s->call);
        }
 
+       vl_active = false;
+
        return 0;
 }
 
@@ -762,6 +775,7 @@ NTSTATUS wb_vl_user_by_name_and_uid(TALLOC_CTX *mem_ctx,
        s = talloc_zero(mem_ctx, struct user_by_name_uid_state);
        if (s == NULL) {
                DBG_ERR("No memory\n");
+               vl_active = 0;
                return NT_STATUS_NO_MEMORY;
        }
        talloc_set_destructor(s, user_by_name_uid_state_destructor);