LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_gpupdate.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 6 67 9.0 %
Date: 2024-04-21 15:09:00 Functions: 1 5 20.0 %

          Line data    Source code
       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             : #include "lib/global_contexts.h"
      24             : 
      25             : /*
      26             :  * gpupdate_interval()
      27             :  * return   Random integer between 5400 and 7200, the group policy update
      28             :  *          interval in seconds
      29             :  *
      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.
      33             :  */
      34             : #define GPUPDATE_INTERVAL       (90*60)
      35             : #define GPUPDATE_RAND_OFFSET    (30*60)
      36           0 : static uint32_t gpupdate_interval(void)
      37             : {
      38           0 :         int rand_int_offset = generate_random() % GPUPDATE_RAND_OFFSET;
      39           0 :         return GPUPDATE_INTERVAL+rand_int_offset;
      40             : }
      41             : 
      42             : struct gpupdate_state {
      43             :         TALLOC_CTX *ctx;
      44             :         struct loadparm_context *lp_ctx;
      45             : };
      46             : 
      47             : static void gpupdate_cmd_done(struct tevent_req *subreq);
      48             : 
      49           0 : static void gpupdate_callback(struct tevent_context *ev,
      50             :                               struct tevent_timer *tim,
      51             :                               struct timeval current_time,
      52             :                               void *private_data)
      53             : {
      54           0 :         struct tevent_timer *time_event;
      55           0 :         struct timeval schedule;
      56           0 :         struct tevent_req *req = NULL;
      57           0 :         struct gpupdate_state *data =
      58           0 :                 talloc_get_type_abort(private_data, struct gpupdate_state);
      59           0 :         const char *const *gpupdate_cmd =
      60           0 :                 lpcfg_gpo_update_command(data->lp_ctx);
      61           0 :         const char *smbconf = lpcfg_configfile(data->lp_ctx);
      62           0 :         if (smbconf == NULL) {
      63           0 :                 smbconf = lp_default_path();
      64             :         }
      65             : 
      66             :         /* Execute gpupdate */
      67           0 :         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           0 :         if (req == NULL) {
      75           0 :                 DEBUG(0, ("Failed to execute the gpupdate command\n"));
      76           0 :                 return;
      77             :         }
      78             : 
      79           0 :         tevent_req_set_callback(req, gpupdate_cmd_done, NULL);
      80             : 
      81             :         /* Schedule the next event */
      82           0 :         schedule = tevent_timeval_current_ofs(gpupdate_interval(), 0);
      83           0 :         time_event = tevent_add_timer(ev, data->ctx, schedule,
      84             :                                       gpupdate_callback, data);
      85           0 :         if (time_event == NULL) {
      86           0 :                 DEBUG(0, ("Failed scheduling the next gpupdate event\n"));
      87             :         }
      88             : }
      89             : 
      90          45 : void gpupdate_init(void)
      91             : {
      92           0 :         struct tevent_timer *time_event;
      93           0 :         struct timeval schedule;
      94          45 :         TALLOC_CTX * ctx = talloc_new(global_event_context());
      95          45 :         struct gpupdate_state *data = talloc(ctx, struct gpupdate_state);
      96           0 :         struct loadparm_context *lp_ctx =
      97          45 :                 loadparm_init_s3(NULL, loadparm_s3_helpers());
      98             : 
      99             :         /*
     100             :          * Check if gpupdate is enabled for winbind, if not
     101             :          * return without scheduling any events.
     102             :          */
     103          45 :         if (!lpcfg_apply_group_policies(lp_ctx)) {
     104          45 :                 return;
     105             :         }
     106             : 
     107             :         /*
     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).
     111             :          */
     112           0 :         schedule = tevent_timeval_current_ofs(0, 0);
     113           0 :         data->ctx = ctx;
     114           0 :         data->lp_ctx = lp_ctx;
     115           0 :         if (data->lp_ctx == NULL) {
     116           0 :                 smb_panic("Could not load smb.conf\n");
     117             :         }
     118           0 :         time_event = tevent_add_timer(global_event_context(), data->ctx,
     119             :                                       schedule, gpupdate_callback, data);
     120           0 :         if (time_event == NULL) {
     121           0 :                 DEBUG(0, ("Failed scheduling the gpupdate event\n"));
     122             :         }
     123             : }
     124             : 
     125           0 : void gpupdate_user_init(const char *user)
     126             : {
     127           0 :         struct tevent_req *req = NULL;
     128           0 :         TALLOC_CTX *ctx = talloc_new(global_event_context());
     129           0 :         struct loadparm_context *lp_ctx =
     130           0 :                 loadparm_init_s3(NULL, loadparm_s3_helpers());
     131           0 :         const char *const *gpupdate_cmd = lpcfg_gpo_update_command(lp_ctx);
     132           0 :         const char *smbconf = lpcfg_configfile(lp_ctx);
     133           0 :         if (smbconf == NULL) {
     134           0 :                 smbconf = lp_default_path();
     135             :         }
     136             : 
     137           0 :         if (ctx == NULL) {
     138           0 :                 DBG_ERR("talloc_new failed\n");
     139           0 :                 return;
     140             :         }
     141             : 
     142             :         /*
     143             :          * Check if gpupdate is enabled for winbind, if not
     144             :          * return without applying user policy.
     145             :          */
     146           0 :         if (!lpcfg_apply_group_policies(lp_ctx)) {
     147           0 :                 return;
     148             :         }
     149             : 
     150             :         /*
     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.
     156             :          */
     157           0 :         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           0 :         if (req == NULL) {
     167           0 :                 DBG_ERR("Failed to execute the gpupdate command\n");
     168           0 :                 return;
     169             :         }
     170             : 
     171           0 :         tevent_req_set_callback(req, gpupdate_cmd_done, NULL);
     172             : }
     173             : 
     174           0 : static void gpupdate_cmd_done(struct tevent_req *subreq)
     175             : {
     176           0 :         int sys_errno;
     177           0 :         int ret;
     178             : 
     179           0 :         ret = samba_runcmd_recv(subreq, &sys_errno);
     180           0 :         TALLOC_FREE(subreq);
     181           0 :         if (ret != 0) {
     182           0 :                 DBG_ERR("gpupdate failed with exit status %d\n", sys_errno);
     183             :         }
     184           0 : }

Generated by: LCOV version 1.14