"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.4.2/src/providers/ldap/sdap_sudo_shared.c" (19 Feb 2021, 7865 Bytes) of package /linux/misc/sssd-2.4.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sdap_sudo_shared.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.1_vs_2.4.2.

    1 /*
    2     Authors:
    3         Pavel Březina <pbrezina@redhat.com>
    4 
    5     Copyright (C) 2015 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 <time.h>
   23 #include <talloc.h>
   24 
   25 #include "util/util.h"
   26 #include "providers/be_ptask.h"
   27 #include "providers/ldap/sdap.h"
   28 #include "providers/ldap/sdap_sudo_shared.h"
   29 #include "db/sysdb_sudo.h"
   30 
   31 errno_t
   32 sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
   33                               struct dp_option *opts,
   34                               be_ptask_send_t full_send_fn,
   35                               be_ptask_recv_t full_recv_fn,
   36                               be_ptask_send_t smart_send_fn,
   37                               be_ptask_recv_t smart_recv_fn,
   38                               void *pvt)
   39 {
   40     time_t smart;
   41     time_t full;
   42     time_t delay;
   43     time_t last_refresh;
   44     errno_t ret;
   45 
   46     smart = dp_opt_get_int(opts, SDAP_SUDO_SMART_REFRESH_INTERVAL);
   47     full = dp_opt_get_int(opts, SDAP_SUDO_FULL_REFRESH_INTERVAL);
   48 
   49     if (smart == 0 && full == 0) {
   50         /* We don't allow both types to be disabled. At least smart refresh
   51          * needs to be enabled. In this case smart refresh will catch up new
   52          * and modified rules and deleted rules are caught when expired. */
   53         smart = opts[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number;
   54 
   55         DEBUG(SSSDBG_CONF_SETTINGS, "At least smart refresh needs to be "
   56               "enabled. Setting smart refresh interval to default value "
   57               "(%ld) seconds.\n", smart);
   58     } else if (full > 0 && full <= smart) {
   59         /* In this case it does not make any sense to run smart refresh. */
   60         smart = 0;
   61 
   62         DEBUG(SSSDBG_CONF_SETTINGS, "Smart refresh interval has to be lower "
   63               "than full refresh interval. Periodical smart refresh will be "
   64               "disabled.\n");
   65     }
   66 
   67     ret = sysdb_sudo_get_last_full_refresh(be_ctx->domain, &last_refresh);
   68     if (ret != EOK) {
   69         DEBUG(SSSDBG_MINOR_FAILURE, "Unable to obtain time of last full "
   70               "refresh. Assuming none was performed so far.\n");
   71         last_refresh = 0;
   72     }
   73 
   74     if (last_refresh == 0) {
   75         /* If this is the first startup, we need to kick off an refresh
   76          * immediately, to close a window where clients requesting sudo
   77          * information won't get an immediate reply with no entries */
   78         delay = 0;
   79     } else {
   80         /* At least one update has previously run, so clients will get cached
   81          * data. We will delay the refresh so we don't slow down the startup
   82          * process if this is happening during system boot. */
   83         delay = 10;
   84     }
   85 
   86     /* Full refresh.
   87      *
   88      * Disable when offline and run immediately when SSSD goes back online.
   89      * Since we have periodical online check we don't have to run this task
   90      * when offline. */
   91     if (full > 0) {
   92         ret = be_ptask_create(be_ctx, be_ctx, full, delay, 0, 0, full,
   93                               0,
   94                               full_send_fn, full_recv_fn, pvt,
   95                               "SUDO Full Refresh",
   96                               BE_PTASK_OFFLINE_DISABLE |
   97                               BE_PTASK_SCHEDULE_FROM_LAST,
   98                               NULL);
   99         if (ret != EOK) {
  100             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup full refresh ptask "
  101                   "[%d]: %s\n", ret, sss_strerror(ret));
  102             return ret;
  103         }
  104     }
  105 
  106     /* Smart refresh.
  107      *
  108      * Disable when offline and reschedule normally when SSSD goes back online.
  109      * Since we have periodical online check we don't have to run this task
  110      * when offline. */
  111     if (smart > 0) {
  112         ret = be_ptask_create(be_ctx, be_ctx, smart, delay + smart, smart, 0,
  113                               smart,                              0,
  114                               smart_send_fn, smart_recv_fn, pvt,
  115                               "SUDO Smart Refresh",
  116                               BE_PTASK_OFFLINE_DISABLE |
  117                               BE_PTASK_SCHEDULE_FROM_LAST,
  118                               NULL);
  119         if (ret != EOK) {
  120             DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup smart refresh ptask "
  121                   "[%d]: %s\n", ret, sss_strerror(ret));
  122             return ret;
  123         }
  124     }
  125 
  126     return EOK;
  127 }
  128 
  129 static char *
  130 sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
  131                   unsigned long usn,
  132                   const char *leftover)
  133 {
  134     const char *str = leftover == NULL ? "" : leftover;
  135     char *newusn;
  136 
  137     /* Current largest USN is unknown so we keep "0" to indicate it. */
  138     if (usn == 0) {
  139         return talloc_strdup(mem_ctx, "0");
  140     }
  141 
  142     /* We increment USN number so that we can later use simplified filter
  143      * (just usn >= last+1 instead of usn >= last && usn != last).
  144      */
  145     usn++;
  146 
  147     /* Convert back to string appending non-converted values since it
  148      * is an indicator that modifyTimestamp is used instead of entryUSN.
  149      * modifyTimestamp contains also timezone specification, usually Z.
  150      * We can't really handle any errors here so we just use what we got. */
  151     newusn = talloc_asprintf(mem_ctx, "%lu%s", usn, str);
  152     if (newusn == NULL) {
  153         DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
  154         return NULL;
  155     }
  156 
  157     return newusn;
  158 }
  159 
  160 void
  161 sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
  162                   const char *usn)
  163 {
  164     unsigned long usn_number;
  165     char *newusn;
  166     char *timezone = NULL;
  167     errno_t ret;
  168 
  169     if (srv_opts == NULL) {
  170         DEBUG(SSSDBG_TRACE_FUNC, "Bug: srv_opts is NULL\n");
  171         return;
  172     }
  173 
  174     if (usn == NULL) {
  175         DEBUG(SSSDBG_TRACE_FUNC, "Bug: usn is NULL\n");
  176         return;
  177     }
  178 
  179     /* If usn == 0 it means that no new rules were found. We will use last known
  180      * USN number as the new highest value. However, we need to get the timezone
  181      * information in case this is a modify timestamp attribute instead of usn.
  182      */
  183     if (!srv_opts->supports_usn && strcmp("0", usn) == 0) {
  184         usn_number = 0;
  185 
  186         /* The value may not be defined yet. */
  187         if (srv_opts->max_sudo_value == NULL) {
  188             timezone = NULL;
  189         } else {
  190             errno = 0;
  191             strtoul(srv_opts->max_sudo_value, &timezone, 10);
  192             if (errno != 0) {
  193                 ret = errno;
  194                 DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s [%d]: %s\n",
  195                       srv_opts->max_sudo_value, ret, sss_strerror(ret));
  196                 return;
  197             }
  198         }
  199     } else {
  200         errno = 0;
  201         usn_number = strtoul(usn, &timezone, 10);
  202         if (errno != 0) {
  203             ret = errno;
  204             DEBUG(SSSDBG_MINOR_FAILURE, "Unable to convert USN %s [%d]: %s\n",
  205                   usn, ret, sss_strerror(ret));
  206             return;
  207         }
  208     }
  209 
  210     if (usn_number > srv_opts->last_usn) {
  211         srv_opts->last_usn = usn_number;
  212     }
  213 
  214     newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone);
  215     if (newusn == NULL) {
  216         return;
  217     }
  218 
  219     talloc_zfree(srv_opts->max_sudo_value);
  220     srv_opts->max_sudo_value = newusn;
  221 
  222     DEBUG(SSSDBG_FUNC_DATA, "SUDO higher USN value: [%s]\n",
  223                              srv_opts->max_sudo_value);
  224 }