winbind: Fix CID 1427625 Calling risky function
[nivanova/samba-autobuild/.git] / source3 / winbindd / winbindd_gpupdate.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Group Policy Update event for winbindd
4  * Copyright (C) David Mulder 2017
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 #include "includes.h"
20 #include "param/param.h"
21 #include "param/loadparm.h"
22 #include "winbindd.h"
23
24 /*
25  * gpupdate_interval()
26  * return   Random integer between 5400 and 7200, the group policy update
27  *          interval in seconds
28  *
29  * Group Policy should be updated every 90 minutes in the background,
30  * with a random offset between 0 and 30 minutes. This ensures mutiple
31  * clients will not update at the same time.
32  */
33 #define GPUPDATE_INTERVAL       (90*60)
34 #define GPUPDATE_RAND_OFFSET    (30*60)
35 static uint32_t gpupdate_interval(void)
36 {
37         int rand_int_offset = generate_random() % GPUPDATE_RAND_OFFSET;
38         return GPUPDATE_INTERVAL+rand_int_offset;
39 }
40
41 struct gpupdate_state {
42         TALLOC_CTX *ctx;
43         struct loadparm_context *lp_ctx;
44 };
45
46 static void gpupdate_callback(struct tevent_context *ev,
47                               struct tevent_timer *tim,
48                               struct timeval current_time,
49                               void *private_data)
50 {
51         struct tevent_timer *time_event;
52         struct timeval schedule;
53         struct tevent_req *req = NULL;
54         struct gpupdate_state *data =
55                 talloc_get_type_abort(private_data, struct gpupdate_state);
56         const char *const *gpupdate_cmd =
57                 lpcfg_gpo_update_command(data->lp_ctx);
58         const char *smbconf = lp_default_path();
59
60         /* Execute gpupdate */
61         req = samba_runcmd_send(data->ctx, ev, timeval_zero(), 2, 0,
62                                 gpupdate_cmd,
63                                 "-s",
64                                 smbconf,
65                                 "--machine",
66                                 "--machine-pass",
67                                 NULL);
68         if (req == NULL) {
69                 DEBUG(0, ("Failed to execute the gpupdate command\n"));
70                 return;
71         }
72
73         /* Schedule the next event */
74         schedule = tevent_timeval_current_ofs(gpupdate_interval(), 0);
75         time_event = tevent_add_timer(ev, data->ctx, schedule,
76                                       gpupdate_callback, data);
77         if (time_event == NULL) {
78                 DEBUG(0, ("Failed scheduling the next gpupdate event\n"));
79         }
80 }
81
82 void gpupdate_init(void)
83 {
84         struct tevent_timer *time_event;
85         struct timeval schedule;
86         TALLOC_CTX * ctx = talloc_new(server_event_context());
87         struct gpupdate_state *data = talloc(ctx, struct gpupdate_state);
88         struct loadparm_context *lp_ctx =
89                 loadparm_init_s3(NULL, loadparm_s3_helpers());
90
91         /*
92          * Check if gpupdate is enabled for winbind, if not
93          * return without scheduling any events.
94          */
95         if (!lpcfg_apply_group_policies(lp_ctx)) {
96                 return;
97         }
98
99         /*
100          * Execute the first event immediately, future events
101          * will execute on the gpupdate interval, which is every
102          * 90 to 120 minutes (at random).
103          */
104         schedule = tevent_timeval_current_ofs(0, 0);
105         data->ctx = ctx;
106         data->lp_ctx = lp_ctx;
107         if (data->lp_ctx == NULL) {
108                 smb_panic("Could not load smb.conf\n");
109         }
110         time_event = tevent_add_timer(server_event_context(), data->ctx,
111                                       schedule, gpupdate_callback, data);
112         if (time_event == NULL) {
113                 DEBUG(0, ("Failed scheduling the gpupdate event\n"));
114         }
115 }
116