From: Samuel Cabrero Date: Wed, 17 Apr 2024 09:58:24 +0000 (+0200) Subject: winbind:varlink: Avoid recursion X-Git-Tag: tevent-0.17.0~730 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=949acb6a9b15578d554e605bfd90c22c4bc3fbec;p=thirdparty%2Fsamba.git winbind:varlink: Avoid recursion 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 Reviewed-by: Andreas Schneider --- diff --git a/source3/winbindd/winbindd_varlink.c b/source3/winbindd/winbindd_varlink.c index 857ea5f14d6..02ef7c32478 100644 --- a/source3/winbindd/winbindd_varlink.c +++ b/source3/winbindd/winbindd_varlink.c @@ -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; } diff --git a/source3/winbindd/winbindd_varlink.h b/source3/winbindd/winbindd_varlink.h index 0508bc689ff..ae30928f8b2 100644 --- a/source3/winbindd/winbindd_varlink.h +++ b/source3/winbindd/winbindd_varlink.h @@ -24,6 +24,8 @@ #include #include +extern bool vl_active; + #define WB_VL_SERVICE_NAME "org.samba.winbind" #define WB_VL_REPLY_ERROR_NO_RECORD_FOUND \ diff --git a/source3/winbindd/winbindd_varlink_getgrouprecord.c b/source3/winbindd/winbindd_varlink_getgrouprecord.c index abb98ece5d1..63e2ddd4358 100644 --- a/source3/winbindd/winbindd_varlink_getgrouprecord.c +++ b/source3/winbindd/winbindd_varlink_getgrouprecord.c @@ -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); diff --git a/source3/winbindd/winbindd_varlink_getmemberships.c b/source3/winbindd/winbindd_varlink_getmemberships.c index cc14062463e..780e99f4f2a 100644 --- a/source3/winbindd/winbindd_varlink_getmemberships.c +++ b/source3/winbindd/winbindd_varlink_getmemberships.c @@ -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) { diff --git a/source3/winbindd/winbindd_varlink_getuserrecord.c b/source3/winbindd/winbindd_varlink_getuserrecord.c index bc6f7781eb7..d96d8f47fb5 100644 --- a/source3/winbindd/winbindd_varlink_getuserrecord.c +++ b/source3/winbindd/winbindd_varlink_getuserrecord.c @@ -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);