LCOV - code coverage report
Current view: top level - providers/ipa - ipa_sudo_refresh.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 176 0.0 %
Date: 2016-06-29 Functions: 0 14 0.0 %

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

Generated by: LCOV version 1.10