diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /source3/winbindd/winbindd_gpupdate.c | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/winbindd/winbindd_gpupdate.c')
-rw-r--r-- | source3/winbindd/winbindd_gpupdate.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/source3/winbindd/winbindd_gpupdate.c b/source3/winbindd/winbindd_gpupdate.c new file mode 100644 index 0000000..1ab20fb --- /dev/null +++ b/source3/winbindd/winbindd_gpupdate.c @@ -0,0 +1,184 @@ +/* + * Unix SMB/CIFS implementation. + * Group Policy Update event for winbindd + * Copyright (C) David Mulder 2017 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include "includes.h" +#include "param/param.h" +#include "param/loadparm.h" +#include "winbindd.h" +#include "lib/global_contexts.h" + +/* + * gpupdate_interval() + * return Random integer between 5400 and 7200, the group policy update + * interval in seconds + * + * Group Policy should be updated every 90 minutes in the background, + * with a random offset between 0 and 30 minutes. This ensures multiple + * clients will not update at the same time. + */ +#define GPUPDATE_INTERVAL (90*60) +#define GPUPDATE_RAND_OFFSET (30*60) +static uint32_t gpupdate_interval(void) +{ + int rand_int_offset = generate_random() % GPUPDATE_RAND_OFFSET; + return GPUPDATE_INTERVAL+rand_int_offset; +} + +struct gpupdate_state { + TALLOC_CTX *ctx; + struct loadparm_context *lp_ctx; +}; + +static void gpupdate_cmd_done(struct tevent_req *subreq); + +static void gpupdate_callback(struct tevent_context *ev, + struct tevent_timer *tim, + struct timeval current_time, + void *private_data) +{ + struct tevent_timer *time_event; + struct timeval schedule; + struct tevent_req *req = NULL; + struct gpupdate_state *data = + talloc_get_type_abort(private_data, struct gpupdate_state); + const char *const *gpupdate_cmd = + lpcfg_gpo_update_command(data->lp_ctx); + const char *smbconf = lpcfg_configfile(data->lp_ctx); + if (smbconf == NULL) { + smbconf = lp_default_path(); + } + + /* Execute gpupdate */ + req = samba_runcmd_send(data->ctx, ev, timeval_zero(), 2, 0, + gpupdate_cmd, + "-s", + smbconf, + "--target=Computer", + "--machine-pass", + NULL); + if (req == NULL) { + DEBUG(0, ("Failed to execute the gpupdate command\n")); + return; + } + + tevent_req_set_callback(req, gpupdate_cmd_done, NULL); + + /* Schedule the next event */ + schedule = tevent_timeval_current_ofs(gpupdate_interval(), 0); + time_event = tevent_add_timer(ev, data->ctx, schedule, + gpupdate_callback, data); + if (time_event == NULL) { + DEBUG(0, ("Failed scheduling the next gpupdate event\n")); + } +} + +void gpupdate_init(void) +{ + struct tevent_timer *time_event; + struct timeval schedule; + TALLOC_CTX * ctx = talloc_new(global_event_context()); + struct gpupdate_state *data = talloc(ctx, struct gpupdate_state); + struct loadparm_context *lp_ctx = + loadparm_init_s3(NULL, loadparm_s3_helpers()); + + /* + * Check if gpupdate is enabled for winbind, if not + * return without scheduling any events. + */ + if (!lpcfg_apply_group_policies(lp_ctx)) { + return; + } + + /* + * Execute the first event immediately, future events + * will execute on the gpupdate interval, which is every + * 90 to 120 minutes (at random). + */ + schedule = tevent_timeval_current_ofs(0, 0); + data->ctx = ctx; + data->lp_ctx = lp_ctx; + if (data->lp_ctx == NULL) { + smb_panic("Could not load smb.conf\n"); + } + time_event = tevent_add_timer(global_event_context(), data->ctx, + schedule, gpupdate_callback, data); + if (time_event == NULL) { + DEBUG(0, ("Failed scheduling the gpupdate event\n")); + } +} + +void gpupdate_user_init(const char *user) +{ + struct tevent_req *req = NULL; + TALLOC_CTX *ctx = talloc_new(global_event_context()); + struct loadparm_context *lp_ctx = + loadparm_init_s3(NULL, loadparm_s3_helpers()); + const char *const *gpupdate_cmd = lpcfg_gpo_update_command(lp_ctx); + const char *smbconf = lpcfg_configfile(lp_ctx); + if (smbconf == NULL) { + smbconf = lp_default_path(); + } + + if (ctx == NULL) { + DBG_ERR("talloc_new failed\n"); + return; + } + + /* + * Check if gpupdate is enabled for winbind, if not + * return without applying user policy. + */ + if (!lpcfg_apply_group_policies(lp_ctx)) { + return; + } + + /* + * Execute gpupdate for the user immediately. + * TODO: This should be scheduled to reapply every 90 to 120 minutes. + * Logoff will need to handle cancelling these events though, and + * multiple timers cannot be run for the same user, even if there are + * multiple active sessions. + */ + req = samba_runcmd_send(ctx, global_event_context(), + timeval_zero(), 2, 0, + gpupdate_cmd, + "-s", + smbconf, + "--target=User", + "-U", + user, + NULL); + if (req == NULL) { + DBG_ERR("Failed to execute the gpupdate command\n"); + return; + } + + tevent_req_set_callback(req, gpupdate_cmd_done, NULL); +} + +static void gpupdate_cmd_done(struct tevent_req *subreq) +{ + int sys_errno; + int ret; + + ret = samba_runcmd_recv(subreq, &sys_errno); + TALLOC_FREE(subreq); + if (ret != 0) { + DBG_ERR("gpupdate failed with exit status %d\n", sys_errno); + } +} |