"Fossies" - the Fresh Open Source Software Archive

Member "sssd-2.4.2/src/providers/ldap/sdap_sudo_refresh.c" (19 Feb 2021, 14644 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_refresh.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 <talloc.h>
   23 #include <tevent.h>
   24 
   25 #include "util/util.h"
   26 #include "providers/be_ptask.h"
   27 #include "providers/ldap/sdap_sudo.h"
   28 #include "providers/ldap/sdap_sudo_shared.h"
   29 #include "db/sysdb_sudo.h"
   30 
   31 struct sdap_sudo_full_refresh_state {
   32     struct sdap_sudo_ctx *sudo_ctx;
   33     struct sdap_id_ctx *id_ctx;
   34     struct sysdb_ctx *sysdb;
   35     struct sss_domain_info *domain;
   36     int dp_error;
   37 };
   38 
   39 static void sdap_sudo_full_refresh_done(struct tevent_req *subreq);
   40 
   41 struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
   42                                                struct sdap_sudo_ctx *sudo_ctx)
   43 {
   44     struct tevent_req *req = NULL;
   45     struct tevent_req *subreq = NULL;
   46     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
   47     struct sdap_sudo_full_refresh_state *state = NULL;
   48     char *search_filter = NULL;
   49     char *delete_filter = NULL;
   50     int ret;
   51 
   52     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_full_refresh_state);
   53     if (req == NULL) {
   54         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
   55         return NULL;
   56     }
   57 
   58     state->sudo_ctx = sudo_ctx;
   59     state->id_ctx = id_ctx;
   60     state->sysdb = id_ctx->be->domain->sysdb;
   61     state->domain = id_ctx->be->domain;
   62 
   63     /* Download all rules from LDAP */
   64     search_filter = talloc_asprintf(state, SDAP_SUDO_FILTER_CLASS,
   65                             id_ctx->opts->sudorule_map[SDAP_AT_SUDO_OC].name,
   66                             id_ctx->opts->sudorule_map[SDAP_OC_SUDORULE].name);
   67     if (search_filter == NULL) {
   68         ret = ENOMEM;
   69         goto immediately;
   70     }
   71 
   72     /* Remove all rules from cache */
   73     delete_filter = talloc_asprintf(state, "(%s=%s)",
   74                                     SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC);
   75     if (delete_filter == NULL) {
   76         ret = ENOMEM;
   77         goto immediately;
   78     }
   79 
   80     DEBUG(SSSDBG_TRACE_FUNC, "Issuing a full refresh of sudo rules\n");
   81 
   82     subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter,
   83                                     delete_filter, true);
   84     if (subreq == NULL) {
   85         ret = ENOMEM;
   86         goto immediately;
   87     }
   88 
   89     tevent_req_set_callback(subreq, sdap_sudo_full_refresh_done, req);
   90 
   91     return req;
   92 
   93 immediately:
   94     if (ret == EOK) {
   95         tevent_req_done(req);
   96     } else {
   97         tevent_req_error(req, ret);
   98     }
   99     tevent_req_post(req, id_ctx->be->ev);
  100 
  101     return req;
  102 }
  103 
  104 static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
  105 {
  106     struct tevent_req *req = NULL;
  107     struct sdap_sudo_full_refresh_state *state = NULL;
  108     int ret;
  109 
  110     req = tevent_req_callback_data(subreq, struct tevent_req);
  111     state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
  112 
  113     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
  114     talloc_zfree(subreq);
  115     if (ret != EOK || state->dp_error != DP_ERR_OK) {
  116         goto done;
  117     }
  118 
  119     /* save the time in the sysdb */
  120     ret = sysdb_sudo_set_last_full_refresh(state->domain, time(NULL));
  121     if (ret != EOK) {
  122         DEBUG(SSSDBG_MINOR_FAILURE, "Unable to save time of "
  123                                     "a successful full refresh\n");
  124         /* this is only a minor error that does not affect the functionality,
  125          * therefore there is no need to report it with tevent_req_error()
  126          * which would cause problems in the consumers */
  127     }
  128 
  129     DEBUG(SSSDBG_TRACE_FUNC, "Successful full refresh of sudo rules\n");
  130 
  131 done:
  132     if (ret != EOK) {
  133         tevent_req_error(req, ret);
  134         return;
  135     }
  136 
  137     tevent_req_done(req);
  138 }
  139 
  140 int sdap_sudo_full_refresh_recv(struct tevent_req *req,
  141                                 int *dp_error)
  142 {
  143     struct sdap_sudo_full_refresh_state *state = NULL;
  144     state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
  145 
  146     TEVENT_REQ_RETURN_ON_ERROR(req);
  147 
  148     *dp_error = state->dp_error;
  149 
  150     return EOK;
  151 }
  152 
  153 struct sdap_sudo_smart_refresh_state {
  154     struct sdap_id_ctx *id_ctx;
  155     struct sysdb_ctx *sysdb;
  156     int dp_error;
  157 };
  158 
  159 static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq);
  160 
  161 struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
  162                                                 struct sdap_sudo_ctx *sudo_ctx)
  163 {
  164     struct tevent_req *req = NULL;
  165     struct tevent_req *subreq = NULL;
  166     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
  167     struct sdap_attr_map *map = id_ctx->opts->sudorule_map;
  168     struct sdap_server_opts *srv_opts = id_ctx->srv_opts;
  169     struct sdap_sudo_smart_refresh_state *state = NULL;
  170     char *search_filter = NULL;
  171     const char *usn;
  172     int ret;
  173 
  174     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_smart_refresh_state);
  175     if (req == NULL) {
  176         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
  177         return NULL;
  178     }
  179 
  180     state->id_ctx = id_ctx;
  181     state->sysdb = id_ctx->be->domain->sysdb;
  182 
  183     /* Download all rules from LDAP that are newer than usn */
  184     if (srv_opts == NULL || srv_opts->max_sudo_value == NULL
  185          || strcmp(srv_opts->max_sudo_value, "0") == 0) {
  186         DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and "
  187               "omitting it from the filter.\n");
  188         usn = "0";
  189         search_filter = talloc_asprintf(state, "(%s=%s)",
  190                                         map[SDAP_AT_SUDO_OC].name,
  191                                         map[SDAP_OC_SUDORULE].name);
  192     } else {
  193         usn = srv_opts->max_sudo_value;
  194         search_filter = talloc_asprintf(state, "(&(%s=%s)(%s>=%s))",
  195                                         map[SDAP_AT_SUDO_OC].name,
  196                                         map[SDAP_OC_SUDORULE].name,
  197                                         map[SDAP_AT_SUDO_USN].name, usn);
  198     }
  199     if (search_filter == NULL) {
  200         ret = ENOMEM;
  201         goto immediately;
  202     }
  203 
  204     /* Do not remove any rules that are already in the sysdb
  205      * sysdb_filter = NULL; */
  206 
  207     DEBUG(SSSDBG_TRACE_FUNC, "Issuing a smart refresh of sudo rules "
  208                              "(USN >= %s)\n", usn);
  209 
  210     subreq = sdap_sudo_refresh_send(state, sudo_ctx, search_filter, NULL, true);
  211     if (subreq == NULL) {
  212         ret = ENOMEM;
  213         goto immediately;
  214     }
  215 
  216     tevent_req_set_callback(subreq, sdap_sudo_smart_refresh_done, req);
  217 
  218     return req;
  219 
  220 immediately:
  221     if (ret == EOK) {
  222         tevent_req_done(req);
  223     } else {
  224         tevent_req_error(req, ret);
  225     }
  226     tevent_req_post(req, id_ctx->be->ev);
  227 
  228     return req;
  229 }
  230 
  231 static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
  232 {
  233     struct tevent_req *req = NULL;
  234     struct sdap_sudo_smart_refresh_state *state = NULL;
  235     int ret;
  236 
  237     req = tevent_req_callback_data(subreq, struct tevent_req);
  238     state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
  239 
  240     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
  241     talloc_zfree(subreq);
  242     if (ret != EOK || state->dp_error != DP_ERR_OK) {
  243         goto done;
  244     }
  245 
  246     DEBUG(SSSDBG_TRACE_FUNC, "Successful smart refresh of sudo rules\n");
  247 
  248 done:
  249     if (ret != EOK) {
  250         tevent_req_error(req, ret);
  251         return;
  252     }
  253 
  254     tevent_req_done(req);
  255 }
  256 
  257 int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
  258                                  int *dp_error)
  259 {
  260     struct sdap_sudo_smart_refresh_state *state = NULL;
  261     state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
  262 
  263     TEVENT_REQ_RETURN_ON_ERROR(req);
  264 
  265     *dp_error = state->dp_error;
  266 
  267     return EOK;
  268 }
  269 
  270 struct sdap_sudo_rules_refresh_state {
  271     struct sdap_id_ctx *id_ctx;
  272     size_t num_rules;
  273     int dp_error;
  274     bool deleted;
  275 };
  276 
  277 static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq);
  278 
  279 struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
  280                                                 struct sdap_sudo_ctx *sudo_ctx,
  281                                                 const char **rules)
  282 {
  283     struct tevent_req *req = NULL;
  284     struct tevent_req *subreq = NULL;
  285     struct sdap_sudo_rules_refresh_state *state = NULL;
  286     struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx;
  287     struct sdap_options *opts = id_ctx->opts;
  288     TALLOC_CTX *tmp_ctx = NULL;
  289     char *search_filter = NULL;
  290     char *delete_filter = NULL;
  291     char *safe_rule = NULL;
  292     int ret;
  293     int i;
  294 
  295     if (rules == NULL) {
  296         return NULL;
  297     }
  298 
  299     tmp_ctx = talloc_new(NULL);
  300     if (tmp_ctx == NULL) {
  301         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
  302         return NULL;
  303     }
  304 
  305     req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_rules_refresh_state);
  306     if (req == NULL) {
  307         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
  308         return NULL;
  309     }
  310 
  311     search_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
  312     delete_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
  313 
  314     /* Download only selected rules from LDAP */
  315     /* Remove all selected rules from cache */
  316     for (i = 0; rules[i] != NULL; i++) {
  317         ret = sss_filter_sanitize(tmp_ctx, rules[i], &safe_rule);
  318         if (ret != EOK) {
  319             ret = ENOMEM;
  320             goto immediately;
  321         }
  322 
  323         search_filter = talloc_asprintf_append_buffer(search_filter, "(%s=%s)",
  324                                      opts->sudorule_map[SDAP_AT_SUDO_NAME].name,
  325                                      safe_rule);
  326         if (search_filter == NULL) {
  327             ret = ENOMEM;
  328             goto immediately;
  329         }
  330 
  331         delete_filter = talloc_asprintf_append_buffer(delete_filter, "(%s=%s)",
  332                                                       SYSDB_SUDO_CACHE_AT_CN,
  333                                                       safe_rule);
  334         if (delete_filter == NULL) {
  335             ret = ENOMEM;
  336             goto immediately;
  337         }
  338     }
  339 
  340     state->id_ctx = sudo_ctx->id_ctx;
  341     state->num_rules = i;
  342 
  343     search_filter = talloc_asprintf(tmp_ctx, "(&"SDAP_SUDO_FILTER_CLASS"(|%s))",
  344                                     opts->sudorule_map[SDAP_AT_SUDO_OC].name,
  345                                     opts->sudorule_map[SDAP_OC_SUDORULE].name,
  346                                     search_filter);
  347     if (search_filter == NULL) {
  348         ret = ENOMEM;
  349         goto immediately;
  350     }
  351 
  352     delete_filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)(|%s))",
  353                                     SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC,
  354                                     delete_filter);
  355     if (delete_filter == NULL) {
  356         ret = ENOMEM;
  357         goto immediately;
  358     }
  359 
  360     subreq = sdap_sudo_refresh_send(req, sudo_ctx, search_filter,
  361                                     delete_filter, false);
  362     if (subreq == NULL) {
  363         ret = ENOMEM;
  364         goto immediately;
  365     }
  366 
  367     tevent_req_set_callback(subreq, sdap_sudo_rules_refresh_done, req);
  368 
  369     ret = EOK;
  370 immediately:
  371     talloc_free(tmp_ctx);
  372 
  373     if (ret != EOK) {
  374         tevent_req_error(req, ret);
  375         tevent_req_post(req, id_ctx->be->ev);
  376     }
  377 
  378     return req;
  379 }
  380 
  381 static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
  382 {
  383     struct tevent_req *req = NULL;
  384     struct sdap_sudo_rules_refresh_state *state = NULL;
  385     size_t downloaded_rules_num;
  386     int ret;
  387 
  388     req = tevent_req_callback_data(subreq, struct tevent_req);
  389     state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
  390 
  391     ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
  392                                  &downloaded_rules_num);
  393     talloc_zfree(subreq);
  394     if (ret != EOK || state->dp_error != DP_ERR_OK) {
  395         goto done;
  396     }
  397 
  398     state->deleted = downloaded_rules_num != state->num_rules ? true : false;
  399 
  400 done:
  401     if (ret != EOK) {
  402         tevent_req_error(req, ret);
  403         return;
  404     }
  405 
  406     tevent_req_done(req);
  407 }
  408 
  409 int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
  410                                  int *dp_error,
  411                                  bool *deleted)
  412 {
  413     struct sdap_sudo_rules_refresh_state *state = NULL;
  414     state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
  415 
  416     TEVENT_REQ_RETURN_ON_ERROR(req);
  417 
  418     *dp_error = state->dp_error;
  419     *deleted = state->deleted;
  420 
  421     return EOK;
  422 }
  423 
  424 static struct tevent_req *
  425 sdap_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx,
  426                                   struct tevent_context *ev,
  427                                   struct be_ctx *be_ctx,
  428                                   struct be_ptask *be_ptask,
  429                                   void *pvt)
  430 {
  431     struct sdap_sudo_ctx *sudo_ctx;
  432     sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
  433 
  434     return sdap_sudo_full_refresh_send(mem_ctx, sudo_ctx);
  435 }
  436 
  437 static errno_t
  438 sdap_sudo_ptask_full_refresh_recv(struct tevent_req *req)
  439 {
  440     int dp_error;
  441 
  442     return sdap_sudo_full_refresh_recv(req, &dp_error);
  443 }
  444 
  445 static struct tevent_req *
  446 sdap_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx,
  447                                    struct tevent_context *ev,
  448                                    struct be_ctx *be_ctx,
  449                                    struct be_ptask *be_ptask,
  450                                    void *pvt)
  451 {
  452     struct sdap_sudo_ctx *sudo_ctx;
  453     sudo_ctx = talloc_get_type(pvt, struct sdap_sudo_ctx);
  454 
  455     return sdap_sudo_smart_refresh_send(mem_ctx, sudo_ctx);
  456 }
  457 
  458 static errno_t
  459 sdap_sudo_ptask_smart_refresh_recv(struct tevent_req *req)
  460 {
  461     int dp_error;
  462 
  463     return sdap_sudo_smart_refresh_recv(req, &dp_error);
  464 }
  465 
  466 errno_t
  467 sdap_sudo_ptask_setup(struct be_ctx *be_ctx, struct sdap_sudo_ctx *sudo_ctx)
  468 {
  469     return sdap_sudo_ptask_setup_generic(be_ctx, sudo_ctx->id_ctx->opts->basic,
  470                                          sdap_sudo_ptask_full_refresh_send,
  471                                          sdap_sudo_ptask_full_refresh_recv,
  472                                          sdap_sudo_ptask_smart_refresh_send,
  473                                          sdap_sudo_ptask_smart_refresh_recv,
  474                                          sudo_ctx);
  475 }