s3:libads: move ads->auth.time_offset to ads->config.time_offset
[Samba.git] / source3 / winbindd / winbindd_gpupdate.c
blob1ab20fb8b83bae81d9d224760ac5c04979b25358
1 /*
2 * Unix SMB/CIFS implementation.
3 * Group Policy Update event for winbindd
4 * Copyright (C) David Mulder 2017
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 #include "includes.h"
20 #include "param/param.h"
21 #include "param/loadparm.h"
22 #include "winbindd.h"
23 #include "lib/global_contexts.h"
26 * gpupdate_interval()
27 * return Random integer between 5400 and 7200, the group policy update
28 * interval in seconds
30 * Group Policy should be updated every 90 minutes in the background,
31 * with a random offset between 0 and 30 minutes. This ensures multiple
32 * clients will not update at the same time.
34 #define GPUPDATE_INTERVAL (90*60)
35 #define GPUPDATE_RAND_OFFSET (30*60)
36 static uint32_t gpupdate_interval(void)
38 int rand_int_offset = generate_random() % GPUPDATE_RAND_OFFSET;
39 return GPUPDATE_INTERVAL+rand_int_offset;
42 struct gpupdate_state {
43 TALLOC_CTX *ctx;
44 struct loadparm_context *lp_ctx;
47 static void gpupdate_cmd_done(struct tevent_req *subreq);
49 static void gpupdate_callback(struct tevent_context *ev,
50 struct tevent_timer *tim,
51 struct timeval current_time,
52 void *private_data)
54 struct tevent_timer *time_event;
55 struct timeval schedule;
56 struct tevent_req *req = NULL;
57 struct gpupdate_state *data =
58 talloc_get_type_abort(private_data, struct gpupdate_state);
59 const char *const *gpupdate_cmd =
60 lpcfg_gpo_update_command(data->lp_ctx);
61 const char *smbconf = lpcfg_configfile(data->lp_ctx);
62 if (smbconf == NULL) {
63 smbconf = lp_default_path();
66 /* Execute gpupdate */
67 req = samba_runcmd_send(data->ctx, ev, timeval_zero(), 2, 0,
68 gpupdate_cmd,
69 "-s",
70 smbconf,
71 "--target=Computer",
72 "--machine-pass",
73 NULL);
74 if (req == NULL) {
75 DEBUG(0, ("Failed to execute the gpupdate command\n"));
76 return;
79 tevent_req_set_callback(req, gpupdate_cmd_done, NULL);
81 /* Schedule the next event */
82 schedule = tevent_timeval_current_ofs(gpupdate_interval(), 0);
83 time_event = tevent_add_timer(ev, data->ctx, schedule,
84 gpupdate_callback, data);
85 if (time_event == NULL) {
86 DEBUG(0, ("Failed scheduling the next gpupdate event\n"));
90 void gpupdate_init(void)
92 struct tevent_timer *time_event;
93 struct timeval schedule;
94 TALLOC_CTX * ctx = talloc_new(global_event_context());
95 struct gpupdate_state *data = talloc(ctx, struct gpupdate_state);
96 struct loadparm_context *lp_ctx =
97 loadparm_init_s3(NULL, loadparm_s3_helpers());
100 * Check if gpupdate is enabled for winbind, if not
101 * return without scheduling any events.
103 if (!lpcfg_apply_group_policies(lp_ctx)) {
104 return;
108 * Execute the first event immediately, future events
109 * will execute on the gpupdate interval, which is every
110 * 90 to 120 minutes (at random).
112 schedule = tevent_timeval_current_ofs(0, 0);
113 data->ctx = ctx;
114 data->lp_ctx = lp_ctx;
115 if (data->lp_ctx == NULL) {
116 smb_panic("Could not load smb.conf\n");
118 time_event = tevent_add_timer(global_event_context(), data->ctx,
119 schedule, gpupdate_callback, data);
120 if (time_event == NULL) {
121 DEBUG(0, ("Failed scheduling the gpupdate event\n"));
125 void gpupdate_user_init(const char *user)
127 struct tevent_req *req = NULL;
128 TALLOC_CTX *ctx = talloc_new(global_event_context());
129 struct loadparm_context *lp_ctx =
130 loadparm_init_s3(NULL, loadparm_s3_helpers());
131 const char *const *gpupdate_cmd = lpcfg_gpo_update_command(lp_ctx);
132 const char *smbconf = lpcfg_configfile(lp_ctx);
133 if (smbconf == NULL) {
134 smbconf = lp_default_path();
137 if (ctx == NULL) {
138 DBG_ERR("talloc_new failed\n");
139 return;
143 * Check if gpupdate is enabled for winbind, if not
144 * return without applying user policy.
146 if (!lpcfg_apply_group_policies(lp_ctx)) {
147 return;
151 * Execute gpupdate for the user immediately.
152 * TODO: This should be scheduled to reapply every 90 to 120 minutes.
153 * Logoff will need to handle cancelling these events though, and
154 * multiple timers cannot be run for the same user, even if there are
155 * multiple active sessions.
157 req = samba_runcmd_send(ctx, global_event_context(),
158 timeval_zero(), 2, 0,
159 gpupdate_cmd,
160 "-s",
161 smbconf,
162 "--target=User",
163 "-U",
164 user,
165 NULL);
166 if (req == NULL) {
167 DBG_ERR("Failed to execute the gpupdate command\n");
168 return;
171 tevent_req_set_callback(req, gpupdate_cmd_done, NULL);
174 static void gpupdate_cmd_done(struct tevent_req *subreq)
176 int sys_errno;
177 int ret;
179 ret = samba_runcmd_recv(subreq, &sys_errno);
180 TALLOC_FREE(subreq);
181 if (ret != 0) {
182 DBG_ERR("gpupdate failed with exit status %d\n", sys_errno);