LCOV - code coverage report
Current view: top level - providers/ldap - sdap_sudo.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 0 576 0.0 %
Date: 2015-10-19 Functions: 0 25 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2011 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <errno.h>
      22             : #include <string.h>
      23             : #include <tevent.h>
      24             : 
      25             : #include "providers/dp_backend.h"
      26             : #include "providers/ldap/ldap_common.h"
      27             : #include "providers/ldap/sdap.h"
      28             : #include "providers/ldap/sdap_async.h"
      29             : #include "providers/ldap/sdap_sudo.h"
      30             : #include "providers/ldap/sdap_sudo_cache.h"
      31             : #include "db/sysdb_sudo.h"
      32             : 
      33             : #define SUDO_MAX_FIRST_REFRESH_DELAY 16
      34             : 
      35             : struct sdap_sudo_full_refresh_state {
      36             :     struct sdap_sudo_ctx *sudo_ctx;
      37             :     struct sdap_id_ctx *id_ctx;
      38             :     struct sysdb_ctx *sysdb;
      39             :     struct sss_domain_info *domain;
      40             :     int dp_error;
      41             :     int error;
      42             : };
      43             : 
      44             : static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
      45             :                                                       struct sdap_sudo_ctx *sudo_ctx);
      46             : 
      47             : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq);
      48             : 
      49             : static int sdap_sudo_full_refresh_recv(struct tevent_req *req,
      50             :                                        int *dp_error,
      51             :                                        int *error);
      52             : 
      53             : struct sdap_sudo_rules_refresh_state {
      54             :     struct sdap_id_ctx *id_ctx;
      55             :     size_t num_rules;
      56             :     int dp_error;
      57             :     int error;
      58             : };
      59             : 
      60             : static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
      61             :                                                        struct sdap_sudo_ctx *sudo_ctx,
      62             :                                                        struct be_ctx *be_ctx,
      63             :                                                        struct sdap_options *opts,
      64             :                                                        struct sdap_id_conn_cache *conn_cache,
      65             :                                                        char **rules);
      66             : 
      67             : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq);
      68             : 
      69             : static int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
      70             :                                         int *dp_error,
      71             :                                         int *error);
      72             : 
      73             : struct sdap_sudo_smart_refresh_state {
      74             :     struct tevent_req *subreq;
      75             :     struct sdap_id_ctx *id_ctx;
      76             :     struct sysdb_ctx *sysdb;
      77             : };
      78             : 
      79             : static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
      80             :                                                       struct sdap_sudo_ctx *sudo_ctx);
      81             : 
      82             : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq);
      83             : 
      84             : static int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
      85             :                                         int *dp_error,
      86             :                                         int *error);
      87             : 
      88             : static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req);
      89             : 
      90             : static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req);
      91             : 
      92             : static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req);
      93             : 
      94             : static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx,
      95             :                                       struct sdap_sudo_ctx *sudo_ctx,
      96             :                                       enum sdap_sudo_refresh_type refresh,
      97             :                                       tevent_req_fn callback,
      98             :                                       time_t delay,
      99             :                                       time_t timeout,
     100             :                                       struct tevent_req **_req);
     101             : 
     102             : static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx,
     103             :                                            time_t delay);
     104             : 
     105             : static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx,
     106             :                                             time_t delay);
     107             : 
     108             : static void
     109           0 : sdap_sudo_shutdown(struct be_req *req)
     110             : {
     111           0 :     sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
     112           0 : }
     113             : 
     114             : struct bet_ops sdap_sudo_ops = {
     115             :     .handler = sdap_sudo_handler,
     116             :     .finalize = sdap_sudo_shutdown
     117             : };
     118             : 
     119             : static void sdap_sudo_get_hostinfo_done(struct tevent_req *req);
     120             : static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx);
     121             : 
     122           0 : int sdap_sudo_init(struct be_ctx *be_ctx,
     123             :                    struct sdap_id_ctx *id_ctx,
     124             :                    struct bet_ops **ops,
     125             :                    void **pvt_data)
     126             : {
     127           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
     128           0 :     struct tevent_req *req = NULL;
     129             :     int ret;
     130             : 
     131           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Initializing sudo LDAP back end\n");
     132             : 
     133           0 :     sudo_ctx = talloc_zero(be_ctx, struct sdap_sudo_ctx);
     134           0 :     if (sudo_ctx == NULL) {
     135           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n");
     136           0 :         return ENOMEM;
     137             :     }
     138             : 
     139           0 :     sudo_ctx->id_ctx = id_ctx;
     140           0 :     *ops = &sdap_sudo_ops;
     141           0 :     *pvt_data = sudo_ctx;
     142             : 
     143             :     /* we didn't do any full refresh now,
     144             :      * so we don't have current usn values available */
     145           0 :     sudo_ctx->full_refresh_done = false;
     146             : 
     147           0 :     ret = ldap_get_sudo_options(be_ctx->cdb,
     148             :                                 be_ctx->conf_path, id_ctx->opts,
     149             :                                 &sudo_ctx->use_host_filter,
     150             :                                 &sudo_ctx->include_regexp,
     151             :                                 &sudo_ctx->include_netgroups);
     152           0 :     if (ret != EOK) {
     153           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot get SUDO options [%d]: %s\n",
     154             :                                   ret, strerror(ret));
     155           0 :         return ret;
     156             :     }
     157             : 
     158           0 :     req = sdap_sudo_get_hostinfo_send(sudo_ctx, id_ctx->opts, be_ctx);
     159           0 :     if (req == NULL) {
     160           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve host information - "
     161             :               "(host filter will be disabled)\n");
     162             : 
     163           0 :         sudo_ctx->use_host_filter = false;
     164             : 
     165           0 :         ret = sdap_sudo_setup_periodical_refresh(sudo_ctx);
     166           0 :         if (ret != EOK) {
     167           0 :              DEBUG(SSSDBG_OP_FAILURE,
     168             :                    "Unable to setup periodical refresh"
     169             :                     "of sudo rules [%d]: %s\n", ret, strerror(ret));
     170             :              /* periodical updates will not work, but specific-rule update
     171             :               * is no affected by this, therefore we don't have to fail here */
     172             :         }
     173             :     } else {
     174           0 :         tevent_req_set_callback(req, sdap_sudo_get_hostinfo_done, sudo_ctx);
     175             :     }
     176             : 
     177           0 :     return EOK;
     178             : }
     179             : 
     180           0 : static void sdap_sudo_get_hostinfo_done(struct tevent_req *req)
     181             : {
     182           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
     183           0 :     char **hostnames = NULL;
     184           0 :     char **ip_addr = NULL;
     185             :     int ret;
     186             : 
     187           0 :     sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
     188             : 
     189           0 :     ret = sdap_sudo_get_hostinfo_recv(sudo_ctx, req, &hostnames, &ip_addr);
     190           0 :     talloc_zfree(req);
     191           0 :     if (ret != EOK) {
     192           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve host information - "
     193             :               "(host filter will be disabled) [%d]: %s\n", ret, strerror(ret));
     194           0 :         sudo_ctx->use_host_filter = false;
     195             :     }
     196             : 
     197           0 :     talloc_zfree(sudo_ctx->hostnames);
     198           0 :     talloc_zfree(sudo_ctx->ip_addr);
     199             : 
     200           0 :     sudo_ctx->hostnames = talloc_move(sudo_ctx, &hostnames);
     201           0 :     sudo_ctx->ip_addr = talloc_move(sudo_ctx, &ip_addr);
     202             : 
     203           0 :     ret = sdap_sudo_setup_periodical_refresh(sudo_ctx);
     204           0 :     if (ret != EOK) {
     205           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to setup periodical refresh"
     206             :                                   "of sudo rules [%d]: %s\n", ret, strerror(ret));
     207             :     }
     208           0 : }
     209             : 
     210           0 : static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx)
     211             : {
     212           0 :     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
     213             :     time_t smart_default;
     214             :     time_t smart_interval;
     215             :     time_t full_interval;
     216             :     time_t last_full;
     217             :     time_t delay;
     218             :     int ret;
     219             : 
     220           0 :     smart_interval = dp_opt_get_int(id_ctx->opts->basic,
     221             :                                     SDAP_SUDO_SMART_REFRESH_INTERVAL);
     222             : 
     223           0 :     full_interval = dp_opt_get_int(id_ctx->opts->basic,
     224             :                                    SDAP_SUDO_FULL_REFRESH_INTERVAL);
     225             : 
     226           0 :     if (smart_interval == 0 && full_interval == 0) {
     227           0 :         smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number;
     228             : 
     229           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "At least one periodical update has to be "
     230             :               "enabled. Setting smart refresh interval to default value (%ld).\n",
     231             :               smart_default);
     232             : 
     233           0 :         ret = dp_opt_set_int(id_ctx->opts->basic,
     234             :                              SDAP_SUDO_SMART_REFRESH_INTERVAL,
     235             :                              smart_default);
     236           0 :         if (ret != EOK) {
     237           0 :             return ret;
     238             :         }
     239             :     }
     240             : 
     241           0 :     if (full_interval <= smart_interval) {
     242           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Full refresh interval has to be greater"
     243             :               "than smart refresh interval. Periodical full refresh will be "
     244             :               "disabled.\n");
     245           0 :         ret = dp_opt_set_int(id_ctx->opts->basic,
     246             :                              SDAP_SUDO_FULL_REFRESH_INTERVAL,
     247             :                              0);
     248           0 :         if (ret != EOK) {
     249           0 :             return ret;
     250             :         }
     251             :     }
     252             : 
     253           0 :     ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->domain,
     254             :                                            &last_full);
     255           0 :     if (ret != EOK) {
     256           0 :         return ret;
     257             :     }
     258             : 
     259           0 :     if (last_full == 0) {
     260             :         /* If this is the first startup, we need to kick off
     261             :          * an refresh immediately, to close a window where
     262             :          * clients requesting sudo information won't get an
     263             :          * immediate reply with no entries
     264             :          */
     265           0 :         delay = 0;
     266             :     } else {
     267             :         /* At least one update has previously run,
     268             :          * so clients will get cached data.
     269             :          * We will delay the refresh so we don't slow
     270             :          * down the startup process if this is happening
     271             :          * during system boot.
     272             :          */
     273             : 
     274             :         /* delay at least by 10s */
     275           0 :         delay = 10;
     276             :     }
     277             : 
     278           0 :     ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
     279             :                                      SDAP_SUDO_REFRESH_FULL,
     280             :                                      sdap_sudo_periodical_first_refresh_done,
     281             :                                      delay, full_interval, NULL);
     282           0 :     if (ret != EOK) {
     283           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
     284             :               "rules! Periodical updates will not work!\n");
     285           0 :         return ret;
     286             :     }
     287             : 
     288           0 :     return EOK;
     289             : }
     290             : 
     291           0 : static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn)
     292             : {
     293             :     unsigned int usn_number;
     294           0 :     char *endptr = NULL;
     295             : 
     296           0 :     if (srv_opts != NULL && usn != NULL) {
     297           0 :         talloc_zfree(srv_opts->max_sudo_value);
     298           0 :         srv_opts->max_sudo_value = talloc_steal(srv_opts, usn);
     299             : 
     300           0 :         usn_number = strtoul(usn, &endptr, 10);
     301           0 :         if ((endptr == NULL || (*endptr == '\0' && endptr != usn))
     302           0 :              && (usn_number > srv_opts->last_usn)) {
     303           0 :              srv_opts->last_usn = usn_number;
     304             :         }
     305             : 
     306           0 :         DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
     307             :                                  srv_opts->max_sudo_value);
     308             :     } else {
     309           0 :         DEBUG(SSSDBG_TRACE_FUNC, "srv_opts is NULL\n");
     310             :     }
     311           0 : }
     312             : 
     313           0 : static char *sdap_sudo_build_host_filter(TALLOC_CTX *mem_ctx,
     314             :                                          struct sdap_attr_map *map,
     315             :                                          char **hostnames,
     316             :                                          char **ip_addr,
     317             :                                          bool netgroups,
     318             :                                          bool regexp)
     319             : {
     320           0 :     TALLOC_CTX *tmp_ctx = NULL;
     321           0 :     char *filter = NULL;
     322             :     int i;
     323             : 
     324           0 :     tmp_ctx = talloc_new(NULL);
     325           0 :     if (tmp_ctx == NULL) {
     326           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     327           0 :         return NULL;
     328             :     }
     329             : 
     330           0 :     filter = talloc_strdup(tmp_ctx, "(|");
     331           0 :     if (filter == NULL) {
     332           0 :         goto done;
     333             :     }
     334             : 
     335             :     /* sudoHost is not specified */
     336           0 :     filter = talloc_asprintf_append_buffer(filter, "(!(%s=*))",
     337           0 :                                            map[SDAP_AT_SUDO_HOST].name);
     338           0 :     if (filter == NULL) {
     339           0 :         goto done;
     340             :     }
     341             : 
     342             :     /* ALL */
     343           0 :     filter = talloc_asprintf_append_buffer(filter, "(%s=ALL)",
     344           0 :                                            map[SDAP_AT_SUDO_HOST].name);
     345           0 :     if (filter == NULL) {
     346           0 :         goto done;
     347             :     }
     348             : 
     349             :     /* hostnames */
     350           0 :     if (hostnames != NULL) {
     351           0 :         for (i = 0; hostnames[i] != NULL; i++) {
     352           0 :             filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
     353           0 :                                                    map[SDAP_AT_SUDO_HOST].name,
     354           0 :                                                    hostnames[i]);
     355           0 :             if (filter == NULL) {
     356           0 :                 goto done;
     357             :             }
     358             :         }
     359             :     }
     360             : 
     361             :     /* ip addresses and networks */
     362           0 :     if (ip_addr != NULL) {
     363           0 :         for (i = 0; ip_addr[i] != NULL; i++) {
     364           0 :             filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
     365           0 :                                                    map[SDAP_AT_SUDO_HOST].name,
     366           0 :                                                    ip_addr[i]);
     367           0 :             if (filter == NULL) {
     368           0 :                 goto done;
     369             :             }
     370             :         }
     371             :     }
     372             : 
     373             :     /* sudoHost contains netgroup - will be filtered more by sudo */
     374           0 :     if (netgroups) {
     375           0 :         filter = talloc_asprintf_append_buffer(filter, SDAP_SUDO_FILTER_NETGROUP,
     376           0 :                                                map[SDAP_AT_SUDO_HOST].name,
     377             :                                                "*");
     378           0 :         if (filter == NULL) {
     379           0 :             goto done;
     380             :         }
     381             :     }
     382             : 
     383             :     /* sudoHost contains regexp - will be filtered more by sudo */
     384             :     /* from sudo match.c :
     385             :      * #define has_meta(s)  (strpbrk(s, "\\?*[]") != NULL)
     386             :      */
     387           0 :     if (regexp) {
     388           0 :         filter = talloc_asprintf_append_buffer(filter,
     389             :                                                "(|(%s=*\\\\*)(%s=*?*)(%s=*\\2A*)"
     390             :                                                  "(%s=*[*]*))",
     391           0 :                                                map[SDAP_AT_SUDO_HOST].name,
     392           0 :                                                map[SDAP_AT_SUDO_HOST].name,
     393           0 :                                                map[SDAP_AT_SUDO_HOST].name,
     394           0 :                                                map[SDAP_AT_SUDO_HOST].name);
     395           0 :         if (filter == NULL) {
     396           0 :             goto done;
     397             :         }
     398             :     }
     399             : 
     400           0 :     filter = talloc_strdup_append_buffer(filter, ")");
     401           0 :     if (filter == NULL) {
     402           0 :         goto done;
     403             :     }
     404             : 
     405           0 :     talloc_steal(mem_ctx, filter);
     406             : 
     407             : done:
     408           0 :     talloc_free(tmp_ctx);
     409             : 
     410           0 :     return filter;
     411             : }
     412             : 
     413           0 : static char *sdap_sudo_get_filter(TALLOC_CTX *mem_ctx,
     414             :                                   struct sdap_attr_map *map,
     415             :                                   struct sdap_sudo_ctx *sudo_ctx,
     416             :                                   const char *rule_filter)
     417             : {
     418           0 :     TALLOC_CTX *tmp_ctx = NULL;
     419           0 :     char *host_filter = NULL;
     420           0 :     char *filter = NULL;
     421             : 
     422           0 :     if (!sudo_ctx->use_host_filter) {
     423           0 :         return talloc_strdup(mem_ctx, rule_filter);
     424             :     }
     425             : 
     426           0 :     tmp_ctx = talloc_new(NULL);
     427           0 :     if (tmp_ctx == NULL) {
     428           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     429           0 :         return NULL;
     430             :     }
     431             : 
     432           0 :     host_filter = sdap_sudo_build_host_filter(tmp_ctx, map,
     433             :                                               sudo_ctx->hostnames,
     434             :                                               sudo_ctx->ip_addr,
     435           0 :                                               sudo_ctx->include_netgroups,
     436           0 :                                               sudo_ctx->include_regexp);
     437           0 :     if (host_filter == NULL) {
     438           0 :         goto done;
     439             :     }
     440             : 
     441           0 :     filter = sdap_get_id_specific_filter(tmp_ctx, rule_filter, host_filter);
     442           0 :     if (filter == NULL) {
     443           0 :         goto done;
     444             :     }
     445             : 
     446           0 :     talloc_steal(mem_ctx, filter);
     447             : 
     448             : done:
     449           0 :     talloc_free(tmp_ctx);
     450           0 :     return filter;
     451             : }
     452             : 
     453           0 : static void sdap_sudo_reply(struct tevent_req *req)
     454             : {
     455           0 :     struct be_req *be_req = NULL;
     456           0 :     struct be_sudo_req *sudo_req = NULL;
     457           0 :     int dp_error = DP_ERR_OK;
     458           0 :     int error = EOK;
     459             :     int ret;
     460             : 
     461           0 :     be_req = tevent_req_callback_data(req, struct be_req);
     462           0 :     sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
     463             : 
     464           0 :     switch (sudo_req->type) {
     465             :     case BE_REQ_SUDO_FULL:
     466           0 :         ret = sdap_sudo_full_refresh_recv(req, &dp_error, &error);
     467           0 :         break;
     468             :     case BE_REQ_SUDO_RULES:
     469           0 :         ret = sdap_sudo_rules_refresh_recv(req, &dp_error, &error);
     470           0 :         break;
     471             :     default:
     472           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
     473             :                                     sudo_req->type);
     474           0 :         ret = EINVAL;
     475             :     }
     476             : 
     477           0 :     talloc_zfree(req);
     478           0 :     if (ret != EOK) {
     479           0 :         sdap_handler_done(be_req, DP_ERR_FATAL, ret, strerror(ret));
     480           0 :         return;
     481             :     }
     482             : 
     483           0 :     sdap_handler_done(be_req, dp_error, error, strerror(error));
     484             : }
     485             : 
     486           0 : void sdap_sudo_handler(struct be_req *be_req)
     487             : {
     488           0 :     struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
     489           0 :     struct tevent_req *req = NULL;
     490           0 :     struct be_sudo_req *sudo_req = NULL;
     491           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
     492           0 :     struct sdap_id_ctx *id_ctx = NULL;
     493           0 :     int ret = EOK;
     494             : 
     495           0 :     sudo_ctx = talloc_get_type(be_ctx->bet_info[BET_SUDO].pvt_bet_data,
     496             :                                struct sdap_sudo_ctx);
     497           0 :     id_ctx = sudo_ctx->id_ctx;
     498             : 
     499           0 :     sudo_req = talloc_get_type(be_req_get_data(be_req), struct be_sudo_req);
     500             : 
     501           0 :     switch (sudo_req->type) {
     502             :     case BE_REQ_SUDO_FULL:
     503           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
     504           0 :         req = sdap_sudo_full_refresh_send(be_req, sudo_ctx);
     505           0 :         break;
     506             :     case BE_REQ_SUDO_RULES:
     507           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Issuing a refresh of specific sudo rules\n");
     508           0 :         req = sdap_sudo_rules_refresh_send(be_req, sudo_ctx, id_ctx->be,
     509           0 :                                            id_ctx->opts, id_ctx->conn->conn_cache,
     510             :                                            sudo_req->rules);
     511           0 :         break;
     512             :     default:
     513           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n",
     514             :                                     sudo_req->type);
     515           0 :         ret = EINVAL;
     516           0 :         goto fail;
     517             :     }
     518             : 
     519           0 :     if (req == NULL) {
     520           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request: %d\n",
     521             :                                     sudo_req->type);
     522           0 :         ret = ENOMEM;
     523           0 :         goto fail;
     524             :     }
     525             : 
     526           0 :     tevent_req_set_callback(req, sdap_sudo_reply, be_req);
     527             : 
     528           0 :     return;
     529             : 
     530             : fail:
     531           0 :     sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
     532             : }
     533             : 
     534             : /* issue full refresh of sudo rules */
     535           0 : static struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
     536             :                                                       struct sdap_sudo_ctx *sudo_ctx)
     537             : {
     538           0 :     struct tevent_req *req = NULL;
     539           0 :     struct tevent_req *subreq = NULL;
     540           0 :     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
     541           0 :     struct sdap_sudo_full_refresh_state *state = NULL;
     542           0 :     char *ldap_filter = NULL;
     543           0 :     char *ldap_full_filter = NULL;
     544           0 :     char *sysdb_filter = NULL;
     545             :     int ret;
     546             : 
     547           0 :     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_full_refresh_state);
     548           0 :     if (req == NULL) {
     549           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     550           0 :         return NULL;
     551             :     }
     552             : 
     553           0 :     sudo_ctx->full_refresh_in_progress = true;
     554             : 
     555           0 :     state->sudo_ctx = sudo_ctx;
     556           0 :     state->id_ctx = id_ctx;
     557           0 :     state->sysdb = id_ctx->be->domain->sysdb;
     558           0 :     state->domain = id_ctx->be->domain;
     559             : 
     560             :     /* Download all rules from LDAP */
     561           0 :     ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
     562           0 :                                   id_ctx->opts->sudorule_map[SDAP_OC_SUDORULE].name);
     563           0 :     if (ldap_filter == NULL) {
     564           0 :         ret = ENOMEM;
     565           0 :         goto immediately;
     566             :     }
     567             : 
     568           0 :     ldap_full_filter = sdap_sudo_get_filter(state, id_ctx->opts->sudorule_map,
     569             :                                             sudo_ctx, ldap_filter);
     570           0 :     if (ldap_full_filter == NULL) {
     571           0 :         ret = ENOMEM;
     572           0 :         goto immediately;
     573             :     }
     574             : 
     575             :     /* Remove all rules from cache */
     576           0 :     sysdb_filter = talloc_asprintf(state, "(%s=%s)",
     577             :                                    SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
     578           0 :     if (sysdb_filter == NULL) {
     579           0 :         ret = ENOMEM;
     580           0 :         goto immediately;
     581             :     }
     582             : 
     583           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
     584             : 
     585           0 :     subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts,
     586           0 :                                     id_ctx->conn->conn_cache,
     587             :                                     ldap_full_filter, sysdb_filter);
     588           0 :     if (subreq == NULL) {
     589           0 :         ret = ENOMEM;
     590           0 :         goto immediately;
     591             :     }
     592             : 
     593           0 :     tevent_req_set_callback(subreq, sdap_sudo_full_refresh_done, req);
     594             : 
     595             :     /* free filters */
     596           0 :     talloc_free(ldap_filter);
     597           0 :     talloc_free(ldap_full_filter);
     598           0 :     talloc_free(sysdb_filter);
     599             : 
     600           0 :     return req;
     601             : 
     602             : immediately:
     603           0 :     if (ret == EOK) {
     604           0 :         tevent_req_done(req);
     605             :     } else {
     606           0 :         tevent_req_error(req, ret);
     607             :     }
     608           0 :     tevent_req_post(req, id_ctx->be->ev);
     609             : 
     610           0 :     return req;
     611             : }
     612             : 
     613           0 : static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
     614             : {
     615           0 :     struct tevent_req *req = NULL;
     616           0 :     struct sdap_sudo_full_refresh_state *state = NULL;
     617           0 :     char *highest_usn = NULL;
     618             :     int ret;
     619             : 
     620           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     621           0 :     state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
     622             : 
     623           0 :     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
     624             :                                  &state->error, &highest_usn, NULL);
     625           0 :     talloc_zfree(subreq);
     626           0 :     if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
     627             :         goto done;
     628             :     }
     629             : 
     630           0 :     state->sudo_ctx->full_refresh_done = true;
     631             : 
     632             :     /* save the time in the sysdb */
     633           0 :     ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL));
     634           0 :     if (ret != EOK) {
     635           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of "
     636             :                                      "a successful full refresh\n");
     637             :         /* this is only a minor error that does not affect the functionality,
     638             :          * therefore there is no need to report it with tevent_req_error()
     639             :          * which would cause problems in the consumers */
     640             :     }
     641             : 
     642           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n");
     643             : 
     644             :     /* set highest usn */
     645           0 :     if (highest_usn != NULL) {
     646           0 :         sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
     647             :     }
     648             : 
     649             : done:
     650           0 :     state->sudo_ctx->full_refresh_in_progress = false;
     651             : 
     652           0 :     if (ret != EOK) {
     653           0 :         tevent_req_error(req, ret);
     654           0 :         return;
     655             :     }
     656             : 
     657           0 :     tevent_req_done(req);
     658             : }
     659             : 
     660           0 : static int sdap_sudo_full_refresh_recv(struct tevent_req *req,
     661             :                                        int *dp_error,
     662             :                                        int *error)
     663             : {
     664           0 :     struct sdap_sudo_full_refresh_state *state = NULL;
     665           0 :     state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
     666             : 
     667           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     668             : 
     669           0 :     *dp_error = state->dp_error;
     670           0 :     *error = state->error;
     671             : 
     672           0 :     return EOK;
     673             : }
     674             : 
     675             : /* issue refresh of specific sudo rules */
     676           0 : static struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
     677             :                                                        struct sdap_sudo_ctx *sudo_ctx,
     678             :                                                        struct be_ctx *be_ctx,
     679             :                                                        struct sdap_options *opts,
     680             :                                                        struct sdap_id_conn_cache *conn_cache,
     681             :                                                        char **rules)
     682             : {
     683           0 :     struct tevent_req *req = NULL;
     684           0 :     struct tevent_req *subreq = NULL;
     685           0 :     struct sdap_sudo_rules_refresh_state *state = NULL;
     686           0 :     TALLOC_CTX *tmp_ctx = NULL;
     687           0 :     char *ldap_filter = NULL;
     688           0 :     char *ldap_full_filter = NULL;
     689           0 :     char *sysdb_filter = NULL;
     690           0 :     char *safe_rule = NULL;
     691             :     int ret;
     692             :     int i;
     693             : 
     694           0 :     if (rules == NULL) {
     695           0 :         return NULL;
     696             :     }
     697             : 
     698           0 :     tmp_ctx = talloc_new(NULL);
     699           0 :     if (tmp_ctx == NULL) {
     700           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     701           0 :         return NULL;
     702             :     }
     703             : 
     704           0 :     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state);
     705           0 :     if (req == NULL) {
     706           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     707           0 :         return NULL;
     708             :     }
     709             : 
     710           0 :     ldap_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
     711           0 :     sysdb_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
     712             : 
     713             :     /* Download only selected rules from LDAP */
     714             :     /* Remove all selected rules from cache */
     715           0 :     for (i = 0; rules[i] != NULL; i++) {
     716           0 :         ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule);
     717           0 :         if (ret != EOK) {
     718           0 :             ret = ENOMEM;
     719           0 :             goto immediately;
     720             :         }
     721             : 
     722           0 :         ldap_filter = talloc_asprintf_append_buffer(ldap_filter, "(%s=%s)",
     723           0 :                                      opts->sudorule_map[SDAP_AT_SUDO_NAME].name,
     724             :                                      safe_rule);
     725           0 :         if (ldap_filter == NULL) {
     726           0 :             ret = ENOMEM;
     727           0 :             goto immediately;
     728             :         }
     729             : 
     730           0 :         sysdb_filter = talloc_asprintf_append_buffer(sysdb_filter, "(%s=%s)",
     731             :                                                      SYSDB_SUDO_CACHE_AT_CN,
     732             :                                                      safe_rule);
     733           0 :         if (sysdb_filter == NULL) {
     734           0 :             ret = ENOMEM;
     735           0 :             goto immediately;
     736             :         }
     737             :     }
     738             : 
     739           0 :     state->id_ctx = sudo_ctx->id_ctx;
     740           0 :     state->num_rules = i;
     741             : 
     742           0 :     ldap_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))",
     743           0 :                                   opts->sudorule_map[SDAP_OC_SUDORULE].name,
     744             :                                   ldap_filter);
     745           0 :     if (ldap_filter == NULL) {
     746           0 :         ret = ENOMEM;
     747           0 :         goto immediately;
     748             :     }
     749             : 
     750           0 :     ldap_full_filter = sdap_sudo_get_filter(tmp_ctx, opts->sudorule_map,
     751             :                                             sudo_ctx, ldap_filter);
     752           0 :     if (ldap_full_filter == NULL) {
     753           0 :         ret = ENOMEM;
     754           0 :         goto immediately;
     755             :     }
     756             : 
     757           0 :     sysdb_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))",
     758             :                                    SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC,
     759             :                                    sysdb_filter);
     760           0 :     if (sysdb_filter == NULL) {
     761           0 :         ret = ENOMEM;
     762           0 :         goto immediately;
     763             :     }
     764             : 
     765           0 :     subreq = sdap_sudo_refresh_send(req, be_ctx, opts, conn_cache,
     766             :                                     ldap_full_filter, sysdb_filter);
     767           0 :     if (subreq == NULL) {
     768           0 :         ret = ENOMEM;
     769           0 :         goto immediately;
     770             :     }
     771             : 
     772           0 :     tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req);
     773             : 
     774           0 :     ret = EOK;
     775             : immediately:
     776           0 :     talloc_free(tmp_ctx);
     777             : 
     778           0 :     if (ret != EOK) {
     779           0 :         tevent_req_error(req, ret);
     780           0 :         tevent_req_post(req, be_ctx->ev);
     781             :     }
     782             : 
     783           0 :     return req;
     784             : }
     785             : 
     786           0 : static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
     787             : {
     788           0 :     struct tevent_req *req = NULL;
     789           0 :     struct sdap_sudo_rules_refresh_state *state = NULL;
     790           0 :     char *highest_usn = NULL;
     791             :     size_t downloaded_rules_num;
     792             :     int ret;
     793             : 
     794           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     795           0 :     state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
     796             : 
     797           0 :     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, &state->error,
     798             :                                  &highest_usn, &downloaded_rules_num);
     799           0 :     talloc_zfree(subreq);
     800           0 :     if (ret != EOK || state->dp_error != DP_ERR_OK || state->error != EOK) {
     801             :         goto done;
     802             :     }
     803             : 
     804             :     /* set highest usn */
     805           0 :     if (highest_usn != NULL) {
     806           0 :         sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
     807             :     }
     808             : 
     809           0 :     if (downloaded_rules_num != state->num_rules) {
     810           0 :         state->error = ENOENT;
     811             :     }
     812             : 
     813             : done:
     814           0 :     if (ret != EOK) {
     815           0 :         tevent_req_error(req, ret);
     816           0 :         return;
     817             :     }
     818             : 
     819           0 :     tevent_req_done(req);
     820             : }
     821             : 
     822           0 : static int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
     823             :                                         int *dp_error,
     824             :                                         int *error)
     825             : {
     826           0 :     struct sdap_sudo_rules_refresh_state *state = NULL;
     827           0 :     state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
     828             : 
     829           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     830             : 
     831           0 :     *dp_error = state->dp_error;
     832           0 :     *error = state->error;
     833             : 
     834           0 :     return EOK;
     835             : }
     836             : 
     837             : /* issue smart refresh of sudo rules */
     838           0 : static struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
     839             :                                                        struct sdap_sudo_ctx *sudo_ctx)
     840             : {
     841           0 :     struct tevent_req *req = NULL;
     842           0 :     struct tevent_req *subreq = NULL;
     843           0 :     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
     844           0 :     struct sdap_attr_map *map = id_ctx->opts->sudorule_map;
     845           0 :     struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
     846           0 :     struct sdap_sudo_smart_refresh_state *state = NULL;
     847           0 :     char *ldap_filter = NULL;
     848           0 :     char *ldap_full_filter = NULL;
     849             :     const char *usn;
     850             :     int ret;
     851             : 
     852           0 :     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
     853           0 :     if (req == NULL) {
     854           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     855           0 :         return NULL;
     856             :     }
     857             : 
     858           0 :     if (!sudo_ctx->full_refresh_done
     859           0 :             && (srv_opts == NULL || srv_opts->max_sudo_value == 0)) {
     860             :         /* Perform full refresh first */
     861           0 :         DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, "
     862             :                                   "waiting for full refresh!\n");
     863           0 :         ret = EINVAL;
     864           0 :         goto immediately;
     865             :     }
     866             : 
     867           0 :     state->id_ctx = id_ctx;
     868           0 :     state->sysdb = id_ctx->be->domain->sysdb;
     869             : 
     870             :     /* Download all rules from LDAP that are newer than usn */
     871           0 :     usn = srv_opts->max_sudo_value;
     872           0 :     if (usn != NULL) {
     873           0 :         ldap_filter = talloc_asprintf(state,
     874             :                                       "(&(objectclass=%s)(%s>=%s)(!(%s=%s)))",
     875             :                                       map[SDAP_OC_SUDORULE].name,
     876           0 :                                       map[SDAP_AT_SUDO_USN].name, usn,
     877           0 :                                       map[SDAP_AT_SUDO_USN].name, usn);
     878             :     } else {
     879             :         /* no valid USN value known */
     880           0 :         ldap_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
     881             :                                       map[SDAP_OC_SUDORULE].name);
     882             :     }
     883           0 :     if (ldap_filter == NULL) {
     884           0 :         ret = ENOMEM;
     885           0 :         goto immediately;
     886             :     }
     887             : 
     888           0 :     ldap_full_filter = sdap_sudo_get_filter(state, map, sudo_ctx, ldap_filter);
     889           0 :     if (ldap_full_filter == NULL) {
     890           0 :         ret = ENOMEM;
     891           0 :         goto immediately;
     892             :     }
     893             : 
     894             :     /* Do not remove any rules that are already in the sysdb
     895             :      * sysdb_filter = NULL; */
     896             : 
     897           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
     898             :                               "(USN > %s)\n", (usn == NULL ? "0" : usn));
     899             : 
     900           0 :     subreq = sdap_sudo_refresh_send(state, id_ctx->be, id_ctx->opts,
     901           0 :                                     id_ctx->conn->conn_cache,
     902             :                                     ldap_full_filter, NULL);
     903           0 :     if (subreq == NULL) {
     904           0 :         ret = ENOMEM;
     905           0 :         goto immediately;
     906             :     }
     907             : 
     908           0 :     state->subreq = subreq;
     909           0 :     tevent_req_set_callback(subreq, sdap_sudo_smart_refresh_done, req);
     910             : 
     911             :     /* free filters */
     912           0 :     talloc_free(ldap_filter);
     913           0 :     talloc_free(ldap_full_filter);
     914             : 
     915           0 :     return req;
     916             : 
     917             : immediately:
     918           0 :     if (ret == EOK) {
     919           0 :         tevent_req_done(req);
     920             :     } else {
     921           0 :         tevent_req_error(req, ret);
     922             :     }
     923           0 :     tevent_req_post(req, id_ctx->be->ev);
     924             : 
     925           0 :     return req;
     926             : }
     927             : 
     928           0 : static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
     929             : {
     930           0 :     struct tevent_req *req = NULL;
     931           0 :     struct sdap_sudo_smart_refresh_state *state = NULL;
     932           0 :     char *highest_usn = NULL;
     933             :     int dp_error;
     934             :     int error;
     935             :     int ret;
     936             : 
     937           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     938           0 :     state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
     939             : 
     940           0 :     ret = sdap_sudo_refresh_recv(state, subreq, &dp_error, &error,
     941             :                                  &highest_usn, NULL);
     942           0 :     if (ret != EOK || dp_error != DP_ERR_OK || error != EOK) {
     943             :         goto done;
     944             :     }
     945             : 
     946           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n");
     947             : 
     948             :     /* set highest usn */
     949           0 :     if (highest_usn != NULL) {
     950           0 :         sdap_sudo_set_usn(state->id_ctx->srv_opts, highest_usn);
     951             :     }
     952             : 
     953             : done:
     954           0 :     if (ret != EOK) {
     955           0 :         tevent_req_error(req, ret);
     956           0 :         return;
     957             :     }
     958             : 
     959           0 :     tevent_req_done(req);
     960             : }
     961             : 
     962           0 : static int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
     963             :                                         int *dp_error,
     964             :                                         int *error)
     965             : {
     966           0 :     struct sdap_sudo_smart_refresh_state *state = NULL;
     967           0 :     state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
     968             : 
     969           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     970             : 
     971           0 :     return sdap_sudo_refresh_recv(state, state->subreq, dp_error, error,
     972             :                                   NULL, NULL);
     973             : }
     974             : 
     975           0 : static void sdap_sudo_full_refresh_online_cb(void *pvt)
     976             : {
     977           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
     978             :     time_t timeout;
     979             :     int ret;
     980             : 
     981           0 :     sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
     982             : 
     983             :     /* remove online callback */
     984           0 :     talloc_zfree(sudo_ctx->first_refresh_online_cb);
     985             : 
     986             :     /* schedule new first refresh only if this callback wasn't triggered
     987             :      * by ongoing full refresh */
     988           0 :     if (sudo_ctx->full_refresh_in_progress) {
     989           0 :         return;
     990             :     }
     991             : 
     992             :     /* otherwise cancel the concurrent timer for full refresh */
     993           0 :     talloc_zfree(sudo_ctx->first_refresh_timer);
     994             : 
     995             :     /* and fire full refresh immediately */
     996           0 :     timeout = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
     997             :                              SDAP_SUDO_FULL_REFRESH_INTERVAL);
     998           0 :     if (timeout == 0) {
     999             :         /* runtime configuration change? */
    1000           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
    1001             :                                   "is disabled\n");
    1002           0 :         return;
    1003             :     }
    1004             : 
    1005           0 :     ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
    1006             :                                      SDAP_SUDO_REFRESH_FULL,
    1007             :                                      sdap_sudo_periodical_first_refresh_done,
    1008             :                                      0, timeout, NULL);
    1009           0 :     if (ret != EOK) {
    1010           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
    1011             :               "rules! Periodical updates will not work!\n");
    1012             :     }
    1013             : }
    1014             : 
    1015           0 : static void sdap_sudo_periodical_first_refresh_done(struct tevent_req *req)
    1016             : {
    1017           0 :     struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */
    1018           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
    1019             :     time_t delay;
    1020             :     time_t timeout;
    1021           0 :     int dp_error = DP_ERR_OK;
    1022           0 :     int error = EOK;
    1023             :     int ret;
    1024             : 
    1025           0 :     ret = sdap_sudo_timer_recv(req, req, &subreq);
    1026           0 :     if (ret != EOK) {
    1027           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1028             :               "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
    1029           0 :         goto schedule;
    1030             :     }
    1031             : 
    1032           0 :     ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error);
    1033           0 :     if (ret != EOK) {
    1034           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
    1035             :                                   "failed [%d]: %s)\n", ret, strerror(ret));
    1036           0 :         goto schedule;
    1037             :     }
    1038             : 
    1039           0 :     if (dp_error != DP_ERR_OK || error != EOK) {
    1040           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
    1041             :                                   "failed [dp_error: %d] ([%d]: %s)\n",
    1042             :                                   dp_error, error, strerror(error));
    1043           0 :         goto schedule;
    1044             :     }
    1045             : 
    1046             : schedule:
    1047           0 :     sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
    1048           0 :     if (sudo_ctx->first_refresh_timer == req) {
    1049           0 :         sudo_ctx->first_refresh_timer = NULL;
    1050             :     }
    1051           0 :     talloc_zfree(req);
    1052             : 
    1053             :     /* full refresh */
    1054           0 :     delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
    1055             :                            SDAP_SUDO_FULL_REFRESH_INTERVAL);
    1056           0 :     if (delay == 0) {
    1057             :         /* runtime configuration change? */
    1058           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
    1059             :                                   "is disabled\n");
    1060           0 :         return;
    1061             :     }
    1062             : 
    1063             :     /* if we are offline, we will try to perform another full refresh */
    1064           0 :     if (dp_error == DP_ERR_OFFLINE) {
    1065           0 :         sudo_ctx->full_refresh_attempts++;
    1066           0 :         timeout = delay;
    1067           0 :         delay = sudo_ctx->full_refresh_attempts << 1;
    1068           0 :         if (delay > SUDO_MAX_FIRST_REFRESH_DELAY) {
    1069           0 :             delay = SUDO_MAX_FIRST_REFRESH_DELAY;
    1070             :         }
    1071             : 
    1072           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Data provider is offline. "
    1073             :               "Scheduling another full refresh in %ld minutes.\n", delay);
    1074             : 
    1075           0 :         ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
    1076             :                                          SDAP_SUDO_REFRESH_FULL,
    1077             :                                          sdap_sudo_periodical_first_refresh_done,
    1078             :                                          delay * 60, timeout,
    1079             :                                          &sudo_ctx->first_refresh_timer);
    1080           0 :         if (ret != EOK) {
    1081           0 :             DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
    1082             :                   "rules! Periodical updates will not work!\n");
    1083             :         }
    1084             : 
    1085             :         /* also setup online callback to make sure the refresh is fired as soon
    1086             :          * as possible */
    1087           0 :         ret = be_add_online_cb(sudo_ctx->id_ctx->be, sudo_ctx->id_ctx->be,
    1088             :                                sdap_sudo_full_refresh_online_cb,
    1089             :                                sudo_ctx, &sudo_ctx->first_refresh_online_cb);
    1090           0 :         if (ret != EOK) {
    1091           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not set up online callback\n");
    1092             :         }
    1093             : 
    1094           0 :         return;
    1095             :     }
    1096             : 
    1097           0 :     ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay);
    1098           0 :     if (ret != EOK) {
    1099           0 :         DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n");
    1100             :     }
    1101             : 
    1102             :     /* smart refresh */
    1103           0 :     delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
    1104             :                            SDAP_SUDO_SMART_REFRESH_INTERVAL);
    1105           0 :     if (delay == 0) {
    1106             :         /* runtime configuration change? */
    1107           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules "
    1108             :                                   "is disabled\n");
    1109           0 :         return;
    1110             :     }
    1111             : 
    1112           0 :     ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay);
    1113           0 :     if (ret != EOK) {
    1114           0 :         DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n");
    1115             :     }
    1116             : }
    1117             : 
    1118           0 : static void sdap_sudo_periodical_full_refresh_done(struct tevent_req *req)
    1119             : {
    1120           0 :     struct tevent_req *subreq = NULL; /* req from sdap_sudo_full_refresh_send() */
    1121           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
    1122             :     time_t delay;
    1123           0 :     int dp_error = DP_ERR_FATAL;
    1124           0 :     int error = EFAULT;
    1125             :     int ret;
    1126             : 
    1127           0 :     ret = sdap_sudo_timer_recv(req, req, &subreq);
    1128           0 :     if (ret != EOK) {
    1129           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1130             :               "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
    1131           0 :         goto schedule;
    1132             :     }
    1133             : 
    1134           0 :     ret = sdap_sudo_full_refresh_recv(subreq, &dp_error, &error);
    1135           0 :     if (ret != EOK) {
    1136           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
    1137             :                                   "failed [%d]: %s)\n", ret, strerror(ret));
    1138           0 :         goto schedule;
    1139             :     }
    1140             : 
    1141           0 :     if (dp_error != DP_ERR_OK || error != EOK) {
    1142           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical full refresh of sudo rules "
    1143             :                                   "failed [dp_error: %d] ([%d]: %s)\n",
    1144             :                                   dp_error, error, strerror(error));
    1145           0 :         goto schedule;
    1146             :     }
    1147             : 
    1148             : schedule:
    1149           0 :     sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
    1150           0 :     talloc_zfree(req);
    1151             : 
    1152           0 :     delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
    1153             :                            SDAP_SUDO_FULL_REFRESH_INTERVAL);
    1154           0 :     if (delay == 0) {
    1155             :         /* runtime configuration change? */
    1156           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Periodical full refresh of sudo rules "
    1157             :                                   "is disabled\n");
    1158           0 :         return;
    1159             :     }
    1160             : 
    1161           0 :     ret = sdap_sudo_schedule_full_refresh(sudo_ctx, delay);
    1162           0 :     if (ret != EOK) {
    1163           0 :         DEBUG(SSSDBG_OP_FAILURE, "Full periodical refresh will not work.\n");
    1164             :     }
    1165             : }
    1166             : 
    1167           0 : static void sdap_sudo_periodical_smart_refresh_done(struct tevent_req *req)
    1168             : {
    1169           0 :     struct tevent_req *subreq = NULL; /* req from sdap_sudo_smart_refresh_send() */
    1170           0 :     struct sdap_sudo_ctx *sudo_ctx = NULL;
    1171             :     time_t delay;
    1172             :     int dp_error;
    1173             :     int error;
    1174             :     int ret;
    1175             : 
    1176           0 :     ret = sdap_sudo_timer_recv(req, req, &subreq);
    1177           0 :     if (ret != EOK) {
    1178           0 :         DEBUG(SSSDBG_OP_FAILURE,
    1179             :               "Sudo timer failed [%d]: %s\n", ret, strerror(ret));
    1180           0 :         goto schedule;
    1181             :     }
    1182             : 
    1183           0 :     ret = sdap_sudo_smart_refresh_recv(subreq, &dp_error, &error);
    1184           0 :     if (ret != EOK) {
    1185           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules "
    1186             :                                   "failed [%d]: %s\n", ret, strerror(ret));
    1187             :     }
    1188             : 
    1189           0 :     if (dp_error != DP_ERR_OK || error != EOK) {
    1190           0 :         DEBUG(SSSDBG_OP_FAILURE, "Periodical smart refresh of sudo rules "
    1191             :                                   "failed [dp_error: %d] ([%d]: %s)\n",
    1192             :                                   dp_error, error, strerror(error));
    1193           0 :         goto schedule;
    1194             :     }
    1195             : 
    1196             : schedule:
    1197           0 :     sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx);
    1198           0 :     talloc_zfree(req);
    1199             : 
    1200           0 :     delay = dp_opt_get_int(sudo_ctx->id_ctx->opts->basic,
    1201             :                            SDAP_SUDO_SMART_REFRESH_INTERVAL);
    1202           0 :     if (delay == 0) {
    1203             :         /* runtime configuration change? */
    1204           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Periodical smart refresh of sudo rules "
    1205             :                                   "is disabled\n");
    1206           0 :         return;
    1207             :     }
    1208             : 
    1209           0 :     ret = sdap_sudo_schedule_smart_refresh(sudo_ctx, delay);
    1210           0 :     if (ret != EOK) {
    1211           0 :         DEBUG(SSSDBG_OP_FAILURE, "Smart periodical refresh will not work.\n");
    1212             :     }
    1213             : }
    1214             : 
    1215           0 : static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx,
    1216             :                                       struct sdap_sudo_ctx *sudo_ctx,
    1217             :                                       enum sdap_sudo_refresh_type refresh,
    1218             :                                       tevent_req_fn callback,
    1219             :                                       time_t delay,
    1220             :                                       time_t timeout,
    1221             :                                       struct tevent_req **_req)
    1222             : {
    1223           0 :     struct tevent_req *req = NULL;
    1224           0 :     sdap_sudo_timer_fn_t send_fn = NULL;
    1225           0 :     const char *name = NULL;
    1226             :     struct timeval when;
    1227             : 
    1228           0 :     when = tevent_timeval_current_ofs(delay, 0);
    1229             : 
    1230           0 :     switch (refresh) {
    1231             :     case SDAP_SUDO_REFRESH_FULL:
    1232           0 :         send_fn = sdap_sudo_full_refresh_send;
    1233           0 :         name = "Full refresh";
    1234           0 :         break;
    1235             :     case SDAP_SUDO_REFRESH_SMART:
    1236           0 :         send_fn = sdap_sudo_smart_refresh_send;
    1237           0 :         name = "Smart refresh";
    1238           0 :         break;
    1239             :     case SDAP_SUDO_REFRESH_RULES:
    1240           0 :         DEBUG(SSSDBG_OP_FAILURE, "Rules refresh can't be scheduled!\n");
    1241           0 :         return EINVAL;
    1242             :     default:
    1243           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unknown refresh type [%d].\n", refresh);
    1244           0 :         return EINVAL;
    1245             :     }
    1246             : 
    1247             : 
    1248             : 
    1249           0 :     req = sdap_sudo_timer_send(mem_ctx, sudo_ctx->id_ctx->be->ev, sudo_ctx,
    1250             :                                when, timeout, send_fn);
    1251           0 :     if (req == NULL) {
    1252           0 :         return ENOMEM;
    1253             :     }
    1254             : 
    1255           0 :     tevent_req_set_callback(req, callback, sudo_ctx);
    1256             : 
    1257           0 :     DEBUG(SSSDBG_TRACE_FUNC, "%s scheduled at: %lld\n",
    1258             :                               name, (long long)when.tv_sec);
    1259             : 
    1260           0 :     if (_req != NULL) {
    1261           0 :         *_req = req;
    1262             :     }
    1263             : 
    1264           0 :     return EOK;
    1265             : }
    1266             : 
    1267           0 : static int sdap_sudo_schedule_full_refresh(struct sdap_sudo_ctx *sudo_ctx,
    1268             :                                            time_t delay)
    1269             : {
    1270             :     int ret;
    1271             : 
    1272           0 :     ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
    1273             :                                      SDAP_SUDO_REFRESH_FULL,
    1274             :                                      sdap_sudo_periodical_full_refresh_done,
    1275             :                                      delay, delay, NULL);
    1276           0 :     if (ret != EOK) {
    1277           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule full refresh of sudo "
    1278             :               "rules!\n");
    1279           0 :         return ret;
    1280             :     }
    1281             : 
    1282           0 :     return EOK;
    1283             : }
    1284             : 
    1285           0 : static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx,
    1286             :                                             time_t delay)
    1287             : {
    1288             :     int ret;
    1289             : 
    1290           0 :     ret = sdap_sudo_schedule_refresh(sudo_ctx, sudo_ctx,
    1291             :                                      SDAP_SUDO_REFRESH_SMART,
    1292             :                                      sdap_sudo_periodical_smart_refresh_done,
    1293             :                                      delay, delay, NULL);
    1294           0 :     if (ret != EOK) {
    1295           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule smart refresh of sudo "
    1296             :               "rules!\n");
    1297           0 :         return ret;
    1298             :     }
    1299             : 
    1300           0 :     return EOK;
    1301             : }

Generated by: LCOV version 1.10